C++ 可以在模板函数中实例化用作模板参数的constexpr c字符串吗?

C++ 可以在模板函数中实例化用作模板参数的constexpr c字符串吗?,c++,clang,c++17,language-lawyer,C++,Clang,C++17,Language Lawyer,我一直在制作一个库的原型,在这个库中,我希望使用函数中本地定义的c字符串值作为非类型模板参数 本质上,最基本的实现如下(请参见上的): #包括 #包括 模板 类编译_字符串{}; 模板 自动foo(){ static constepr char const CSTR[]=“你好,世界!”; 返回编译字符串{}; } int main(){ 自动短路=foo(); auto inty=foo(); 返回标准::是否相同; } 当用最新的clang(11.0)编译这个短程序时,在O1到O3中,一切

我一直在制作一个库的原型,在这个库中,我希望使用函数中本地定义的c字符串值作为非类型模板参数

本质上,最基本的实现如下(请参见上的):

#包括
#包括
模板
类编译_字符串{};
模板
自动foo(){
static constepr char const CSTR[]=“你好,世界!”;
返回编译字符串{};
}
int main(){
自动短路=foo();
auto inty=foo();
返回标准::是否相同;
}
当用最新的clang(11.0)编译这个短程序时,在O1到O3中,一切都很好,但是当用O0编译时,链接失败

尽管装配部分包含:

; foo<short>()::CSTR
_ZZ3fooIsEDavE4CSTR:
        .asciz  "Hello, World!"

; foo<int>()::CSTR
_ZZ3fooIiEDavE4CSTR:
        .asciz  "Hello, World!"
传递
-Xlinker--no demangle
此错误变为:

/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/example-35000b.o:(.debug_info+0x1be): undefined reference to `_ZZ3foovE4CSTR'
人们意识到,
foo
的模板参数不知何故被剥离了

注:

  • Gcc(7.3和10.2)成功编译了这个示例
  • 程序集中没有提到
    \u ZZ3foovE4CSTR
    ,也没有提到其他两个变体,老实说,这可能就是启用优化“解决”问题的原因

上述程序是否符合C++17标准?

(因此,我是否注意到了铿锵编译器的问题?)


另外一个问题:有什么办法可以绕过这个问题吗?

我觉得这句话有点奇怪:“
/opt/compiler explorer/gcc-10.2.0/lib/gcc/x86\u 64-linux-gnu/10.2.0/../../../../../x86\u 64-linux-gnu/bin/ld
”@JHBonarius:我也觉得有点奇怪;特别是当我在GCC10.2和Clang11.0之间切换时。然后,在这种情况下,这可能只是指向平台链接器的链接?嗯,AST似乎是正确的,但IR显示了一条奇怪的线
@ZZ3foovE4CSTR=external dso_Localconstant[14 x i8],align 1
。开始有点问题了。我想你需要在函数模板中定义CSTR,对吗?把它拿出来也解决了这个问题。这个问题似乎是由返回参数引起的。您可以制作第二个CSTR(例如CSTR2)并切换模板。返回类型的param更改生成的外部符号。@JHBonarius:是的,目标是创建一个可在任何函数/lambda中使用的宏,因此字符串和实例化需要在此特定上下文中进行。我不确定我是否了解CSTR2的诀窍,你有一个godbolt链接来说明你的意思吗?嗯,我错了。
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/example-35000b.o:(.debug_info+0x1be): undefined reference to `_ZZ3foovE4CSTR'