#include <iostream>
using namespace std;
template<typename T> void print(T&& mX)
{
std::cout << std::forward<T>(mX) << std::endl;
}
struct SomeStruct
{
static constexpr const char* someString{"hello!"};
SomeStruct()
{
print(someString);
}
};
int main()
{
SomeStruct s{};
return 0;
}
clang++ -std=c++1y ./code.cpp -o code.o
/tmp/code-a049fe.o:在函数 `SomeStruct::SomeStruct()' 中:
./code.cpp:(.text._ZN10SomeStructC2Ev[_ZN10SomeStructC2Ev]+0xa):
对 `SomeStruct::someString' 的未定义引用 clang:错误:链接器
命令失败,退出代码为 1(使用 -v 查看调用)
g++ -std=c++1y ./code.cpp -o code.o
/tmp/ccyrTsjS.o:在函数 `SomeStruct::SomeStruct()' 中:
代码.cpp:(.text._ZN10SomeStructC2Ev[_ZN10SomeStructC5Ev]+0xd):
对“SomeStruct::someString”collect2 的未定义引用:错误:ld
返回 1 退出状态
为什么会发生这个链接器错误?不是someString
应该可以在编译时解析吗?
另外,如果满足以下条件,则不会发生错误print(someString)
被替换为cout << someString;
因为您正在获取引用,所以该变量是 odr 使用的,这需要一个超出范围的定义:
constexpr const char* SomeStruct::someString;
看到它实时运行 http://coliru.stacked-crooked.com/a/ecd786eb2f72b231.
来自 C++14 标准草案部分3.2
[基本.def.odr]:
名称显示为潜在求值表达式 ex 的变量 x 被 ex odr 使用,除非应用
x 的左值到右值转换(4.1)产生一个常量表达式(5.20),它不会调用任何非平凡的
函数,如果 x 是对象,则 ex 是表达式 e 的潜在结果集合的元素,
其中左值到右值转换 (4.1) 应用于 e,或者 e 是丢弃值表达式 [...]
例如以下替代方案print
不会使用 ODRsomeString
:
template<typename T> void print(T mX)
{
std::cout << mX << std::endl;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)