clang 上的静态 constexpr 未定义引用错误
static constexpr undefined reference error on clang
以下代码在 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;
}
clang 的错误是:
... undefined reference to `repo::x'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Compiler returned: 1
在 SO 上也有类似的问题,即 未定义的引用错误,静态 constexpr 数据成员,但是 none 向我解释了为什么这段代码无法编译叮当响。上面3)
中的代码有问题吗?
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;
编辑:
需要注意的是,优化关闭,none of the examples成功link。
这是优化器的产物,有时,对一个值的引用可以被扁平化为该值本身,在这种情况下,linker 不会'不要寻找丢失的符号。
使用 https://godbolt.org/z/edj6Ed 我验证程序编译并运行 gcc >= 7,但失败并出现与 6.4 的 clang 相同的错误,前提是使用
-std=c++17
(其实我用的是-pedantic -std=c++17
).
Clang++ 从版本 5.0.0 开始也可以很好地编译您的程序,这是第一个支持 C++17 的版本。它总是以 std=C++14
.
失败
在引用 static constexpr
的 C++17 中发生了什么?
A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline.
Pre-C++17,如果是ODR-used.
,则需要定义static constexpr
变量
在您的示例中,x
使用 ODR,因为它作为参数传递给 pair
构造函数,后者通过引用获取值。因此,您需要对其进行定义。
以下代码在 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;
}
clang 的错误是:
... undefined reference to `repo::x'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Compiler returned: 1
在 SO 上也有类似的问题,即 未定义的引用错误,静态 constexpr 数据成员,但是 none 向我解释了为什么这段代码无法编译叮当响。上面3)
中的代码有问题吗?
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;
编辑:
需要注意的是,优化关闭,none of the examples成功link。
这是优化器的产物,有时,对一个值的引用可以被扁平化为该值本身,在这种情况下,linker 不会'不要寻找丢失的符号。
使用 https://godbolt.org/z/edj6Ed 我验证程序编译并运行 gcc >= 7,但失败并出现与 6.4 的 clang 相同的错误,前提是使用
-std=c++17
(其实我用的是-pedantic -std=c++17
).
Clang++ 从版本 5.0.0 开始也可以很好地编译您的程序,这是第一个支持 C++17 的版本。它总是以 std=C++14
.
在引用 static constexpr
的 C++17 中发生了什么?
A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline.
Pre-C++17,如果是ODR-used.
,则需要定义static constexpr
变量
在您的示例中,x
使用 ODR,因为它作为参数传递给 pair
构造函数,后者通过引用获取值。因此,您需要对其进行定义。