lll*_*lll 6 c++ constexpr clang++ c++14 c++17
请考虑以下代码:
#include <iostream>
template<class T>
struct foo {};
template<>
struct foo<int> {
static constexpr char value[] = "abcde";
};
template<class T>
struct bar {
static constexpr char value[] = "abcde";
};
template<class T>
struct baz {
static constexpr int value = 12345;
};
int main() {
char c = foo<int>::value[2];
char d = bar<int>::value[2];
int e = baz<int>::value;
std::cout << c << d << e << "\n";
}
Run Code Online (Sandbox Code Playgroud)
使用:编译时clang++ -std=c++14 ./test_foo.cc,我得到未定义符号的链接器错误:bar<int>::value和foo<int>::value.当我改为时clang++ -std=c++17,只有一个未定义的符号:foo<int>::value.我的clang ++版本是5.0.
但是,当我尝试时g++ -std=c++14 ./test_foo.cc,编译成功.我的g ++版本是5.4.0.
我有两件事要问.
1)从C++标准的角度来看,哪个编译器行为正确?
我用Google搜索并阅读了许多cppreference页面,但没有找到任何与此现象真正相关的内容.特别是对于clang ++ with -std=c++17,行为真的很奇怪,因为bar<int>已经通过但foo<int>失败了,唯一的区别就是foo<int>专业化.我从http://en.cppreference.com/w/cpp/language/constexpr上读到
函数或静态成员变量(自C++ 17)声明中使用的constexpr说明符暗示内联.
因此,模板专业化似乎没有理由foo<int>失败.此外,我看着生成的目标文件链接之前,该访问foo<int>::value[2];是不是在编译时完成正如人们所预料的那样.我非常怀疑clang ++编译器有什么问题.
2)如何处理这个clang ++链接错误?
我试过像undedefined引用静态constexpr char [],但最后我找不到任何方法来克服这个链接错误.所以我只是想知道是否有办法让这种连接成功.
在 C++17 之前,原因与您发现的问题中所述的完全相同(我认为 Shafik Yaghmour 发布的答案更准确地解释了这个问题)。简而言之,如果静态数据成员是odr-used 的constexpr,则仍然需要定义该成员。
在 C++17 之前,您可以通过提供这些变量的定义来解决该问题(即使用)。-std=c++14
自 C++17 起, [dcl.constexpr] 第 1 段中的当前标准表示
\n\n\n\n\n\n\n...使用说明符声明的函数或静态数据成员
\nconstexpr隐式是内联函数或变量([dcl.inline])。
\n\n\n声明是定义,除非
\n\n\n
\n- \n
...
- \n
它在类定义中声明一个非内联静态数据成员([class.mem],[class.static]),
- \n
...
因此不需要命名空间范围内的此类定义。
\n\n此外,当前标准[depr.static_constexpr] 第 1 段说
\n\n\n\n\n为了与先前的 C++ 国际标准兼容,可以在类外部冗余地重新声明 constexpr 静态数据成员,而无需初始化程序。这种用法已被弃用。[\xe2\x80\x89示例:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nstruct A {\n static constexpr int n = 5; // definition (declaration in C++ 2014)\n};\n\nconstexpr int A::n; // redundant declaration (definition in C++ 2014)\n\xe2\x80\x94\xe2\x80\x89结束示例\xe2\x80\x89]
\n
所以从 C++17 开始你最好避免这样的定义。
\n\n\n\n\n当我更改为 时
\nclang++ -std=c++17,则只有一个未定义的符号:foo<int>::value。
这是一个 Clang 错误。无论如何,它对于 Clang HEAD 7.0.0 来说效果很好。
\n| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |