Per*_*-lk 4 c++ static constexpr c++11
这项工作:
template<typename T> struct Something
{ static constexpr const char* str = "int"; };
int main()
{ std::cout << Something<int>::str << std::endl; }
Run Code Online (Sandbox Code Playgroud)
但它没有:
template<typename T> struct Something
{ static constexpr const char str[] = "int"; };
int main()
{ std::cout << Something<int>::str << std::endl; }
Run Code Online (Sandbox Code Playgroud)
gcc-4.8说:"未定义参考Something<int>::str".
可以解决此错误,定义类外的静态成员:
template<typename T>
constexpr const char Something<T>::name[];
Run Code Online (Sandbox Code Playgroud)
为什么它不是指针而是数组?static constexpr毕竟两者都是会员.
Bri*_*ian 10
如果使用了odr,则必须定义一个对象或函数.在某些情况下,对象和函数不会使用,在这种情况下,您不必定义它们.无论静态类成员的声明是否具有初始化程序,它仍然不是定义.在所有情况下,规则是如果静态成员使用了odr,则需要在封闭的命名空间范围内进行类外定义.
直觉是"odr-used"意味着"链接器需要它的地址".如果constexpr变量仅以需要其值的方式使用 - 而且从不使用其地址 - 则可以避免使用它.在这种情况下,编译器只是简单地内联其值,并且不需要定义它,因为链接器不需要其地址.情况就是如此const char* Something<int>::str,但不是const char Something<int>::str[].
"但他们是一样的!",你喊道.不是这样.对于when str是a const char*,其值是字符串文字的地址"int".需要字符串文字的地址,但不需要str自己的地址.前者是它的价值,str它满足了不被使用的要求; 编译器可以内联它.但是当它str是a时const char[],它的值就是字符串文字"int"本身.当您尝试使用istream::operator<<它输出时,它会隐式转换为const char*.但const char*的值是地址字符串文字,也就是地址的Something<int>::str.因此,在这种情况下Something<int>::str使用odr; 它的地址是必需的.
标准中有逻辑可用于精确确定变量的使用时间([basic.def.odr]).但我不会引用它,因为它是整个标准中最令人困惑的部分.我会说,在你有的情况下,const char* Something<int>::str立即应用左值到右值的转换,这是它不被使用的条件之一; 如果你有const char Something<int>::str[],则立即应用数组到指针的转换,并且不满足条件.
| 归档时间: |
|
| 查看次数: |
1315 次 |
| 最近记录: |