y0p*_*rst 17 c++ definition constexpr c++17
考虑以下代码:
#include <vector>
struct A {
static constexpr int kDefaultValue = -1;
std::vector<int> v;
A(int n): v(n, A::kDefaultValue) {}
};
int main() {
A(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它无法链接(llvm clang,gcc 4.9,两者都在OS X上):
Undefined symbols for architecture x86_64:
"A::kDefaultValue", referenced from:
A::(int) in main.cpp.o
ld: symbol(s) not found for architecture x86_64
Run Code Online (Sandbox Code Playgroud)
问题是它有什么问题?它可以通过static_cast-ing A::kDefaultValue来修复int.或者搬出kDefaultValue去A.两个案件似乎都很难看.这是另一种使它链接的方式吗?
Wal*_*ter 20
这种行为让我一次又一次烦恼.麻烦的原因是你的
A(int n): v(n, A::kDefaultValue) {}
Run Code Online (Sandbox Code Playgroud)
ODR-使用的static constexpr构件中,由于构造v需要一个恒定的参考第二个参数.错误使用需要在某处定义,即
const int A::kDefaultValue;
Run Code Online (Sandbox Code Playgroud)
在一些编译单元(编译和链接到main()).此要求已在C++ 17中删除,并且相应的定义(如上所述)已弃用.
但是,定义并不总是可行的(例如对于类模板的成员)并且避免定义和错误的最简单方法是
A(int n): v(n, int(A::kDefaultValue)) {}
Run Code Online (Sandbox Code Playgroud)
这会创建一个临时传递给构造函数v(但由于后者是完全内联的,编译器可能会优化它).
son*_*yao 11
自C++ 17以来,行为发生了变化.在C++ 17之前,即使是一个constexpr静态数据成员也必须在类定义中初始化,仍然需要在命名空间范围内定义; 从C++ 17开始,不再需要命名空间范围定义.
如果静态数据成员声明为constexpr,则它是隐式内联的,不需要在命名空间范围内重新声明.没有初始化程序(以前需要如上所示)的重新声明仍然允许,但已弃用.(自C++ 17起)
使用支持C++ 17的编译器编译代码可以正常工作.
| 归档时间: |
|
| 查看次数: |
6358 次 |
| 最近记录: |