以下代码使用枚举成员m作为常量表达式,即作为模板参数.代码在gcc下编译,但不在clang(现场演示)下编译.Clang说"错误:非类型模板参数不是常量表达式".
这个问题可以通过交换行来解决// 1的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
}
};
Run Code Online (Sandbox Code Playgroud)
根据标准,Clang 拒绝该代码是正确的。
t2.m是类成员访问表达式。[expr.ref]/1 说:
[...] 计算点或箭头之前的后缀表达式;该评估的结果与id-expression一起确定整个后缀表达式的结果。
还有一个注释:
如果对类成员访问表达式进行求值,则即使不需要结果来确定整个后缀表达式的值,也会发生子表达式求值,例如,如果 id 表达式表示静态成员。
因此,子表达式t2被求值。[expr.const]/2.9 表示如果对某个表达式e求值导致求值,则该表达式不能是核心常量表达式
引用引用类型的变量或数据成员的id 表达式,除非引用具有前面的初始化并且
- 它用常量表达式初始化或
- 它的生命周期开始于 的评估
e;
t2指的是不满足项目符号的引用类型变量,因此t2.m不是常量表达式,因为它不是核心常量表达式。
所有引用均来自当前发布的工作草案 N4594。自 C++11 以来,文本略有变化,但本例中的含义是相同的。
| 归档时间: |
|
| 查看次数: |
418 次 |
| 最近记录: |