如何解决对静态 constexpr 的未定义引用,如果作为带有 O0 的函数参数包传递适用于更高的优化级别
以下代码片段只有在优化级别高于 O0 时才能链接:
#include <cstdio>
#include <utility>
void vf(std::size_t n,...) {printf("%zu\n",n);}
template<typename ...ARGS> void vt(ARGS&&... args) {vf( sizeof...(ARGS),std::forward<ARGS>(args)... );}
struct X {static constexpr int a = 123; X() {vt(a);}};
int main() {X();}
您可以在这里运行它:http://cpp.sh/3dv7p
使用 O0 配置 C++11/14 将失败并显示以下链接器错误:
/tmp/cc1xC4HI.o: In function `X::X()':
:(.text._ZN1XC2Ev[_ZN1XC5Ev]+0xd): undefined reference to `X::a'
collect2: error: ld returned 1 exit status
选择 O1、O2 或 O3 将链接成功,程序执行返回预期输出。
解决方案
表明这个问题与可变参数模板函数无关。唯一的问题是,编译器优化是否在编译时 (>O0) 或链接时 (O0) 期间替换了 static constexpr
成员。在后一种情况下,X::a
的声明也需要一些有效的定义。这可以通过将 constexpr int X::a;
添加到上述代码段来完成。生成的代码段将与任何优化级别链接:
#include <cstdio>
#include <utility>
void vf(std::size_t n,std::forward<ARGS>(args)... );}
struct X {static constexpr int a = 123; X() {vt(a);}};
constexpr int X::a;
int main() {X();}
请注意,对于 static constexpr
成员,需要在声明时进行初始化,具有完整的类型,而不是在定义时。
为了让编译器在编译时已经替换,也使用 O0,不应传递对 X::a
的引用。这就是为什么此代码段也能成功与 O0 链接的原因,即使它没有 X::a
的定义:
#include <cstdio>
#include <utility>
void vf(std::size_t n,n);}
template<typename ...ARGS> void vt(ARGS... args) {vf( sizeof...(ARGS),std::forward<ARGS>(args)... );}
struct X {static constexpr int a = 123; X() {vt(a);}};
int main() {X();}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。