我有一段简单的代码,它包装了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()
);它编译了OK,但是如果我在最后的两行中用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(); }
^它应该这么做吗?
发布于 2015-09-18 22:33:23
decltype(unparenthesized class member access)返回引用的实体的声明类型。
decltype((class member access))返回一些不同的内容。如果类成员访问表达式的类型是T,则返回的类型是T& (如果表达式是lvalue )、T&& (表达式是xvalue )和T (表达式是prvalue )。
在CWG 616之前,如果E2为非引用类型的非静态数据成员命名,那么E1.E2具有与E1相同的值类别。因此,给定struct A { double x; };,decltype(A().x)和decltype((A().x))都是double (A()是prvalue)。
在CWG 616之后,如果E1.E2是一个lvalue,那么E1现在是一个lvalue,而xvalue则是另一个值(同样,当E2指定一个非引用类型的非静态数据成员时)。所以decltype(A().x)应该是double,decltype((A().x))应该是double &&。
因为CWG 616是一个缺陷报告,所以它可以追溯应用;您的原始代码不应该在符合标准的编译器中编译。
您观察到的实际行为似乎是编译器错误。即使它没有实现CWG 616的解析,标准的任何修订版也不能让它区分timespec().tv_nsec和Timespec().tv_nsec,或者使decltype((timespec().tv_nsec))返回一个lvalue引用。
https://stackoverflow.com/questions/32661665
复制相似问题