下面的代码可以在VisualStudio2019和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;
}来自clang的错误是:
... undefined reference to `repo::x'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Compiler returned: 1在这一点上也有类似的问题,例如未定义的引用错误、静态的constexpr数据成员,但没有一个问题向我解释了为什么这段代码不能在clang上编译。上面的3)中的代码有问题吗?
发布于 2021-02-01 20:23:27
C++17引入了static constexpr成员变量是隐式inline (P0386)的规则。内联变量在C++17之前不存在。
这意味着在早期的C++标准中,编译器可能需要定义static constexpr成员变量。例如,如果它的地址被取下来。
在早于C++17的C++标准中,您可以通过单独定义( static变量)来确保代码格式良好。
struct repo {
static constexpr const char *x = "sth";
};
constexpr const char *repo::x;编辑:
它是优化器的一个工件,有时可以将对值的引用还原到值本身,在这种情况下,链接器不会查找缺少的符号。
发布于 2021-02-01 20:25:13
使用https://godbolt.org/z/edj6Ed,我验证了该程序编译和运行gcc >= 7,但失败的错误与您的clang为6.4,的条件是使用
-std=c++17(实际上我使用了-pedantic -std=c++17)。
Clang++还从5.0.0版本开始编译程序,这是第一个支持C++17的版本,std=C++14总是失败的。
在C++17中发生了什么,指的是static constexpr
函数或静态成员变量(因为C++17)声明中使用的constexpr说明符意味着内联。
发布于 2021-02-01 21:11:50
在C++17之前,如果static constexpr变量是ODR-使用,则需要定义它.
在您的示例中,x是使用ODR的,因为它被作为参数传递给pair构造函数,该构造函数通过引用来获取值。因此,您需要它的定义。
https://stackoverflow.com/questions/65999130
复制相似问题