Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 静态constexpr变量可以用作模板参数吗_C++_Templates_Constexpr - Fatal编程技术网

C++ 静态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

我有下面一段代码,它在较旧的gcc上编译,但在版本6上没有(与-std=c++1z一起使用)。Clang也拒绝了,说对象val没有正确的链接。我不明白有什么区别。指针类型的constexpr变量不是应该或多或少透明地工作吗?我的语法中是否缺少了一些可以让它工作的东西?或者这违反了标准的某些部分

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之间缺陷报告引入的两个澄清:

  • 澄清关于完整对象的位
  • 最后添加了最后一个项目符号
对于C++17,由于采用了本文(中的基本原理),限制已被放宽。相应的第(2)款现在说:

非类型模板参数的模板参数应为 类型的转换常量表达式(5.20) 模板参数。对于引用的非类型模板参数或 指针类型,常量表达式的值不应引用 (或对于指针类型,不应为的地址):

  • 子对象(1.8)
  • 临时物体(12.2)
  • 字符串文字(2.13.5)
  • typeid
    表达式(5.2.8)的结果,或
  • 预定义的
    \uuuu func\uuu
    变量(8.4.1)
[注意:如果模板参数表示一组重载 函数(或指向此类函数的指针或成员指针),匹配 从集合中选择功能(13.4)。-结束注释]


对每一个项目都有很好的解释。

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标准的额外信息,以及它是如何变化的。无论如何,谢谢。