带有静态constexpr const char *和完美转发的链接器错误(未定义引用)

Vit*_*meo 3 c++ linker constexpr perfect-forwarding c++14

#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;
}
Run Code Online (Sandbox Code Playgroud)

clang++ -std=c++1y ./code.cpp -o code.o

/tmp/code-a049fe.o:在函数“ SomeStruct :: SomeStruct()”中:./code.cpp:(.text._ZN10SomeStructC2Ev[_ZN10SomeStructC2Ev]+0xa):未定义对“ SomeStruct :: someString”的引用:错误:链接器命令失败,退出代码为1(使用-v查看调用)


g++ -std=c++1y ./code.cpp -o code.o

/tmp/ccyrTsjS.o:在函数“ SomeStruct :: SomeStruct()”中:code.cpp :(。text._ZN10SomeStructC2Ev [_ZN10SomeStructC5Ev] + 0xd):未定义对“ SomeStruct :: someString”的引用collect2:错误:trud退出状态


为什么发生此链接器错误?难道someString在编译时就无法解决吗?

另外,如果print(someString)将其替换为错误,则不会发生cout << someString;

Sha*_*our 5

因为您正在引用,所以该变量是odd-used,并且这需要一个异常定义:

constexpr const char* SomeStruct::someString;
Run Code Online (Sandbox Code Playgroud)

看到它现场工作

在C ++ 14标准草案3.2 [basic.def.odr]中

变量x的名称显示为可能值表达式ex,否则ex会使用它,除非对x进行左值到右值转换(4.1)会产生不调用任何平凡函数的常量表达式(5.20),如果x是对象,ex是表达式e的一组潜在结果的元素,其中,将左值到右值转换(4.1)应用于e,或者e是舍弃值表达式[...]

例如,以下替代方法print将不能odr-use someString

template<typename T> void print(T mX) 
{
    std::cout << mX << std::endl;  
}
Run Code Online (Sandbox Code Playgroud)