C++ 静态constexpr变量可以用作模板参数吗
我有下面一段代码,它在较旧的gcc上编译,但在版本6上没有(与-std=c++1z一起使用)。Clang也拒绝了,说对象val没有正确的链接。我不明白有什么区别。指针类型的constexpr变量不是应该或多或少透明地工作吗?我的语法中是否缺少了一些可以让它工作的东西?或者这违反了标准的某些部分C++ 静态constexpr变量可以用作模板参数吗,c++,templates,constexpr,C++,Templates,Constexpr,我有下面一段代码,它在较旧的gcc上编译,但在版本6上没有(与-std=c++1z一起使用)。Clang也拒绝了,说对象val没有正确的链接。我不明白有什么区别。指针类型的constexpr变量不是应该或多或少透明地工作吗?我的语法中是否缺少了一些可以让它工作的东西?或者这违反了标准的某些部分 typedef void(*t_voidfn)(); template <t_voidfn> struct s {}; void fn() { static constexpr t_voi
typedef void(*t_voidfn)();
template <t_voidfn> struct s {};
void fn() {
static constexpr t_voidfn val = &fn;
s<val> x;
}
typedef void(*t_voidfn)();
模板结构s{};
无效fn(){
静态constexpr t_voidfn val=&fn;
sx;
}
另一方面,这一个有效
typedef void(*t_voidfn)();
template <t_voidfn> struct s {};
void fn() {
s<&fn> x;
}
typedef void(*t_voidfn)();
模板结构s{};
无效fn(){
sx;
}
第一个代码片段在C++17中是正确的,但在C++14和11中不是正确的
对于C++14,[temp.arg.nontype]/1表示:
非类型、非模板的模板参数
模板参数应为以下参数之一:
[……]
- 一种常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部数据的完整对象的地址
联动装置或具有外部或内部联动装置的功能,包括
函数模板和函数模板ID,但不包括
非静态类成员,表示(忽略括号)为
id表达式,其中id表达式是对象或函数的名称,但如果名称引用 函数或数组,如果相应的 模板参数是一个参考;或&
- 计算为空指针值的常量表达式(4.10);或
- 计算结果为空成员指针值的常量表达式(4.11);或
- 指向构件的指针,如5.3.1所述;或
类型的常量表达式std::nullptr\u t
&fn
或fn
C++11包含基本相同的措辞,减去11和14之间缺陷报告引入的两个澄清:
- 澄清关于完整对象的位李>
- 最后添加了最后一个项目符号
- 子对象(1.8)
- 临时物体(12.2)
- 字符串文字(2.13.5)
表达式(5.2.8)的结果,或typeid
- 预定义的
变量(8.4.1)\uuuu func\uuu
对每一个项目都有很好的解释。there的static关键字没有将变量设置为private,而是将其设置为具有持久存储的运行时值,在第一次调用函数时进行初始化…@KerrekSB,但我没有获取变量的地址,我使用的是它的值,它在编译时被初始化为具有明显可接受链接的某个对象的地址,因为该值单独起作用。错误消息没有多大帮助。这意味着函数的地址必须严格表示为
&fn
或fn
。这只是C++14及以下版本标准中规定的一个限制,C++17取消了该限制。这就是代码以C++1z模式在两个编译器上编译的原因。抄送@KerrekSB@bogdan在c++17之前,此限制是明确要求的还是未指定的。我询问的原因是gcc-4.8.5和gcc-5.3.0接受有效的代码。或者这是gcc-6中修复的gcc错误?@bogdan我想你应该写一个答案,这样我就可以接受了。我希望您能提供一些关于c++11、14、17标准的额外信息,以及它是如何变化的。无论如何,谢谢。