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



我有一段简单的代码,它包装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(); }
                                               ^

它应该这样做吗?

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

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

在 CWG 616 之前,如果 E2 命名非引用类型的非静态数据成员,则E1.E2具有与 E1 相同的值类别。所以给定struct A { double x; };decltype(A().x)decltype((A().x))都是double(A()是一个prvalue(。

在 CWG 616 之后,如果E1.E2是左值,则E1现在是左值,否则是 x值(同样,当E2命名非引用类型的非静态数据成员时(。所以decltype(A().x)应该doubledecltype((A().x))应该double &&.

由于 CWG 616 是缺陷报告,因此具有追溯性;您的原始代码不应在符合要求的编译器中进行编译。

您观察到的实际行为似乎是编译器错误。即使它没有实现CWG 616的决议,该标准的任何修订版中也没有任何内容允许它区分timespec().tv_nsecTimespec().tv_nsec,或使decltype((timespec().tv_nsec))返回一个左值引用。

相关内容

最新更新