我有一段简单的代码,它包装了 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&&
如果表达式是一个 xvalue,如果表达式是一个 prvalue,则为 T
。
之前CWG 616 ,如果 E2
命名了一个非引用类型的非静态数据成员,那么 E1.E2
与 E1
具有相同的值类别。所以给定 struct A { double x; };
,decltype(A().x)
和decltype((A().x))
都是double
(A()
是纯右值)。
在 CWG 616 之后,如果 E1
是左值,则 E1.E2
现在是左值,否则是 xvalue(同样,当 E2
命名非引用类型的非静态数据成员)。所以 decltype(A().x)
应该是 double
而 decltype((A().x))
应该是 double &&
。
由于 CWG 616 是一份缺陷报告,因此它具有追溯力;您的原始代码不应在符合标准的编译器中编译。
您观察到的实际行为似乎是一个编译器错误。即使它没有实现 CWG 616 的决议,标准的任何修订版也没有任何内容允许它区分 timespec().tv_nsec
和 Timespec().tv_nsec
,或者让 decltype((timespec().tv_nsec))
返回一个左值引用。
关于c++ - 简单的继承——奇怪的编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32661665/