【问题标题】:Another problem with decltypedecltype 的另一个问题
【发布时间】:2011-05-03 19:42:43
【问题描述】:
//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&lt;T&gt;'
错误(来自 gcc 4.6)
error: 'decltype ((lhs-&gt;getValue() + rhs-&gt;getValue()))' is not a valid type for a template constant parameter

为什么这没有像我想象的那样工作?

【问题讨论】:

  • 请注意,要将getValue 标记为constexpr,您的构造函数需要标记为constexpr,以便value_ 可以成为常量表达式。

标签: c++ friend decltype


【解决方案1】:

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

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

问题是模板非类型参数不能是右值引用,所以你不能有Int&lt;int&amp;&amp;&gt;,因为第二个参数的类型。不过,您可以这样做:

#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&amp;&amp; 的引用,为您提供裸int 类型。希望 gcc 的错误消息更有意义:它试图告诉您不能将 int&amp;&amp; 用于您的非类型参数。


另一个问题,虽然可能不是问题,是整数运算经历了所谓的usual arithmetic conversions。所以两个Int&lt;char&gt;的值相加的结果实际上是int,所以你的返回类型应该是Int&lt;int&gt;(并且是,使用固定代码)。

那么,问题在于您还没有定义static_numeric_limits&lt;int&gt;。但就像我说的,我怀疑这不是问题,你确实已经定义了它,只是没有显示在你的问题中。

【讨论】:

  • @GMan 这是一个很棒的答案。谢谢。你知道为什么那些反对票吗?这个问题有什么问题?
  • @There:讨论很大,但被删除了。人们觉得你发布了一个咆哮而不是一个问题,因为你最后的陈述,所以关闭它并否决了它。我认为事实并非如此,并通过编辑进行了澄清,并建议人们只是决定将其视为咆哮,因为他们不喜欢您的其他问题。不管谁是对的,问题被重新打开,cmets 被删除。不过,在未来,尽量让您的问题尽可能清晰,并尽量减少您的任何想法或挫败感。
  • @GMan 很抱歉,但我的帖子的哪一部分表示咆哮?看在上帝的份上,就不能发表个人意见吗?我以什么方式侮辱或激怒了任何人?太可笑了。
  • @GMan 它会编译,但最后你会得到不正确的结果。很抱歉(好吧,我们走了),但是非常慢的 2010 是如此的错误,以至于实际上不可能使用它进行实际工作(使用 C++0x)。 C++ 的每一个可能的特性在这个编译器中都是错误的。可悲。
  • 仅仅因为 "0 + 0" 产生一个右值并不意味着 decltype(0 + 0) 是 int&&,就像 xvalue vs prvalue distinction matters 一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多