简单的继承 - 奇怪的编译器错误

时间:2015-09-18 21:59:43

标签: c++ c++11 gcc

我有这段简单的代码包裹struct timespec并添加静态成员的最小值和最大值。

#include <sys/stat.h>
#include <limits>
struct Timespec : public timespec {
    Timespec() :timespec() {};
    Timespec(decltype(tv_sec) s, 
                     decltype(tv_nsec) ns
            ) {
        tv_sec = s;
        tv_nsec = ns;
    }
    static const Timespec max;
    static const Timespec min;
};

const Timespec Timespec::min  = Timespec(0,0);
const Timespec Timespec::max  = Timespec(
        std::numeric_limits<decltype((timespec().tv_sec))>::max(), 
        std::numeric_limits<decltype((timespec().tv_nsec))>::max()
    );

它编译正常,但如果我用decltype((timespec()/*...*/替换  在最后的两行中decltype((Timespec()/*...*/,我得到:

$ make timespec.o
g++ -std=c++0x   -c -o timespec.o timespec.cc
In file included from timespec.cc:2:0:
/usr/include/c++/4.8/limits: In instantiation of ‘static constexpr _Tp std::numeric_limits<_Tp>::max() [with _Tp = long int&]’:
timespec.cc:18:55:   required from here
/usr/include/c++/4.8/limits:313:48: error: value-initialization of reference type ‘long int&’
       max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); }
                                                ^
/usr/include/c++/4.8/limits:313:51: error: body of constexpr function ‘static constexpr _Tp std::numeric_limits<_Tp>::max() [with _Tp = long int&]’ not a return-statement
       max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); }
                                               ^

它应该这样做吗?

1 个答案:

答案 0 :(得分:5)

decltype(unparenthesized class member access)返回所引用实体的声明类型。

decltype((class member access))会返回不同的内容。如果类成员访问表达式的类型为T,则表达式为左值时返回的类型为T&,如果表达式为x值,则返回T&&T如果表达式是prvalue。

CWG 616之前,如果E2为非参考类型的非静态数据成员命名,则E1.E2具有与E1相同的值类别。因此,struct A { double x; };decltype(A().x)decltype((A().x))都是doubleA()是prvalue)。

在CWG 616之后,如果E1.E2是左值,E1现在是左值,否则是{值}(再次,当E2命名非参考的非静态数据成员时类型)。因此decltype(A().x)应为doubledecltype((A().x))应为double &&

由于CWG 616是缺陷报告,因此追溯适用;您的原始代码不应该在符合标准的编译器中编译。

您观察到的实际行为似乎是编译器错误。即使它没有实施CWG 616的分辨率,标准的任何修订都不允许它区分timespec().tv_nsecTimespec().tv_nsec,或使decltype((timespec().tv_nsec))返回左值参考