以下代码使用枚举成员m
作为常量表达式,即作为模板参数。该代码可以在 gcc 下编译,但不能在 clang 下编译(现场演示 http://coliru.stacked-crooked.com/a/79f0d052864fec19%20live%20demo)。 Clang 说“错误:非类型模板参数不是常量表达式”。
可以通过换线解决问题// 1
by A<tst<p>::m> a
。因此,我的问题不是如何解决这个问题,而是哪个编译器是正确的。
template<size_t n> struct A{};
template<size_t n>
struct tst
{ enum : size_t { m= n % 15 };
template<size_t p>
void
call( tst<p> const &t2 ) {
A<t2.m> a; // 1
}
};
根据标准,Clang 拒绝该代码是正确的。
t2.m
是类成员访问表达式。 [expr.ref]/1 说:
[...] 计算点或箭头之前的后缀表达式;这
该评估的结果,连同id-表达式,
确定整个后缀表达式的结果。
还有一个注释:
如果计算类成员访问表达式,则子表达式
即使结果对于确定结果来说是不必要的,也会进行评估
整个后缀表达式的值,例如如果id-表达式表示静态成员。
所以,子表达式t2
被评估。 [expr.const]/2.9 表示一个表达式e
如果评估它会导致评估以下内容,则不能是核心常量表达式
an id-表达式引用引用的变量或数据成员
类型,除非引用有前面的初始化并且
- 它用常量表达式初始化或
- 它的生命周期开始于评估
e
;
t2
指的是不满足项目符号的引用类型变量,因此t2.m
不是常量表达式,因为它不是核心常量表达式。
所有引用均来自当前发布的工作草案 N4594。自 C++11 以来,文本略有变化,但本例中的含义是相同的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)