decltype的另一个问题

Another problem with decltype

本文关键字:问题 另一个 decltype      更新时间:2023-10-16
//THIS IS JUST A FRAGMENT OF A static_numeric_limits.h for the purpose of this example   
 #include <limits.h>
    template<class T>
    struct static_numeric_limits;
    template<>
    struct static_numeric_limits<signed char>
    {/*min was outside of range for enum*/
        static const signed char min = SCHAR_MIN,
                                 max = SCHAR_MAX;
    };
    /*This "surplus" template is here for the reason that char is threated differently from signed char */
    template<>
    struct static_numeric_limits<char>
    {/*min was outside of range for enum*/
        static const char min = SCHAR_MIN,
                          max = SCHAR_MAX;
    };
    template<>
    struct static_numeric_limits<unsigned char>
    {
        static const unsigned char min = 0x0,
                             max = UCHAR_MAX;
    };
 ///REAL PROBLEM STARTS FROM HERE      
     template<class IntType,IntType low_range = static_numeric_limits<IntType>::min>
    struct Int
    {
        Int():value_(IntType())
        {}
        Int(const IntType& pattern)
        {
            value_ = (pattern);
        }
        constexpr inline IntType getValue()const
        {
            return value_;
        }
    private:
        IntType value_;
    };
    template<class IntType,class IntType_1>
    auto operator+
        (Int<IntType>& lhs, Int<IntType_1>& rhs)
        -> Int<decltype(lhs.getValue() + rhs.getValue())>//HERE IS THE PROBLEM
    {
        return lhs.getValue() + rhs.getValue();
    }

错误(来自VS2010)error C2027: use of undefined type 'static_numeric_limits<T>'
错误(来自gcc 4.6)
error: 'decltype ((lhs->getValue() + rhs->getValue()))' is not a valid type for a template constant parameter

为什么它不像我想象的那样工作?

这里的错误是什么类型的decltype是从你的表达式推导;不幸的是,错误信息并不清楚,这实际上是一个有点棘手的问题。

考虑表达式0 + 0的类型。它是一个int,是的,但更重要的是它是一个右值(非正式地,它是一个临时值)。这意味着decltype(0 + 0)不是int,而是int&&。现在考虑一下你的代码在这方面没有什么不同:你仍然有一个右值。

问题是模板非类型形参不能是右值引用,所以不能有Int<int&&>,因为第二个形参的类型。但是,您可以这样做:

#include <type_traits>
// ...
template <class IntType, class IntType_1>
auto operator+(const Int<IntType>& lhs, // be const-correct!
                const Int<IntType_1>& rhs)
                -> Int<typename std::remove_reference<
                        decltype(lhs.getValue() + rhs.getValue())>::type>
{
    return lhs.getValue() + rhs.getValue();
}

这将从int&&中取出引用,给您一个赤裸裸的int类型。希望gcc的错误信息更有意义:它试图告诉您不能将int&&用于非类型参数。


另一个问题(虽然可能不是问题)是整数算术要经过所谓的常规算术转换。因此,将两个Int<char>的值相加的结果实际上将是一个int,因此您的返回类型应该是Int<int>(并且是固定代码)。

问题是,你没有定义static_numeric_limits<int>。但就像我说的,我怀疑这不是问题,你实际上已经定义了它,只是没有显示在你的问题中。