[英]can a static constexpr variable be used as a template argument
我有以下代码编译旧的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)();
template <t_voidfn> struct s {};
void fn() {
s<&fn> x;
}
第一个片段在C ++ 17中是正确的,但在C ++ 14和11中则没有。
对于C ++ 14,[temp.arg.nontype] / 1表示:
模板参数的用于非类型的,非模板的模板参数应是以下之一:
[...]
- 一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或具有外部或内部链接的函数,包括函数模板和函数模板ID,但不包括非静态类成员,表达(忽略括号)作为
&
ID表达 ,其中的ID-expression是对象或函数的名称,除了&
如果名称是指功能或阵列,并且如果相应的模板的参数是将被省略,可以省略参考; 要么- 一个常量表达式,其值为空指针值(4.10); 要么
- 一个常量表达式,其值为null成员指针值(4.11); 要么
- 指向成员的指针,如5.3.1所述; 要么
std::nullptr_t
类型的常量表达式。
(我只包括与指针直接相关的子弹和指向成员的指针。)
基本上,样本中函数的地址必须严格表示为&fn
或fn
。
C ++ 11包含基本相同的措辞,减去11和14之间缺陷报告引入的一些说明:
对于C ++ 17,由于采用了N4268纸( N4198中的基本原理 ),因此放宽了这些限制。 相应的第(2)段现在说:
模板参数的用于非类型模板参数应为模板参数的类型的一个转换后的常量表达式(5.20)。 对于引用或指针类型的非类型模板参数 ,常量表达式的值不应引用(或者对于指针类型,不应该是地址):
- 子对象(1.8),
- 一个临时物体(12.2),
- 字符串文字(2.13.5),
typeid
表达式的结果(5.2.8),或- 预定义的
__func__
变量(8.4.1)。[ 注意:如果template-argument表示一组重载函数(或指向此类的指针或成员指针),则从集合中选择匹配函数(13.4)。 - 结束说明 ]
N4198对每个子弹都有很好的解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.