clang 上的 static constexpr 未定义引用错误

Fra*_*cis 6 c++ clang constexpr

以下代码在 Visual Studio 2019 和 gcc 10.2(以及其他 gcc 版本)上可以正常编译,-std=c++11但在 clang(版本 9、10 和 11)上编译失败。

#include <map>
#include <string>

struct repo {
    static constexpr const char *x = "sth";
};

int main() {

    // 1) This compiles
    std::map<std::string, int> m1 = { {repo::x, 3} };
    
    // 2) This compiles
    std::map<std::string, std::string> m2 = { std::make_pair(repo::x, "") };
    
    // 3) This does not compile on clang
    std::map<std::string, std::string> m3 = { {repo::x, ""} };

    return 0;
}

Run Code Online (Sandbox Code Playgroud)

clang 的错误是:

... undefined reference to `repo::x'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

在这方面也有类似的问题,即Undefined reference error, static constexpr data member,但没有一个问题向我解释为什么这段代码不能在 clang 上编译。上面的代码有问题吗3)

Dre*_*ann 6

static constexprC++17 引入了成员变量是隐式的规则inline( P0386 )。C++17 之前不存在内联变量。

这意味着在早期的 C++ 标准中,编译器可能需要static constexpr定义成员变量。例如,如果其地址被占用。

在 C++17 之前的 C++ 标准中,您可以通过单独定义变量来确保代码格式良好static

struct repo {
    static constexpr const char *x = "sth";
};

constexpr const char *repo::x;
Run Code Online (Sandbox Code Playgroud)

编辑:

应该注意的是,在关闭优化的情况下,没有一个示例能够成功链接。

这是优化器的一个产物,有时,对值的引用可以扁平化为值本身,在这种情况下,链接器不会查找丢失的符号。