使用枚举作为常量表达式.哪个编译器是正确的
Using an enum as a constant expression. Which compiler is right?
以下代码使用枚举成员m
作为常量表达式,即作为模板参数。代码在 gcc 下编译,但不在 clang 下编译(现场演示)。Clang 说"错误:非类型模板参数不是常量表达式"。
这个问题可以通过A<tst<p>::m> a
交换线路// 1
来解决。因此,我的问题不是如何解决这个问题,而是哪个编译器是正确的。
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-expression 表示静态成员。
因此,将计算子表达式t2
。[expr.const]/2.9 表示表达式e
不能是核心常量表达式,如果计算表达式
引用引用的变量或数据成员的 ID 表达式 类型,除非引用具有前面的初始化,并且
- 它使用常量表达式或
- 它的生命周期始于对
e
的评估;
t2
引用类型的变量不满足项目符号,因此t2.m
不是常量表达式,因为它不是核心常量表达式。
所有引文均来自N4594,当前发布的工作草案。自 C++11 以来,文本略有变化,但在这种情况下的含义是相同的。
相关文章:
- 编译器是否强制根据模板参数计算表达式?
- C++正则表达式失败(GCC vs Microsoft 编译器)
- 编译器错误:函数调用在常量表达式中必须有一个常量值
- 在 C++ 中使用带有正则表达式的 G++ 和 Visual Studio 14 2015 编译器时会产生不同的结果
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 说编译器可以将下面的表达式"a->i"替换为其值 1 是否正确,因为...?
- enable_if_t 中带有折叠表达式的编译器错误
- 表达式未评估为常数两个级别的constexpr函数(编译器错误?)
- 视觉C++ 2017 错误?编译器优化表达式
- 现代编译器可以优化表达式从函数得出的常数表达式
- 为什么表达式末尾的重复和更多分号不会导致 Visual Studio 编译器中的错误
- 编译器在常量表达式中认为未定义的行为方面是否允许回旋余地?
- 内联 lambda 表达式会导致编译器错误
- 编译器计算常量表达式
- ::运算符 new 是不允许在 lambda 表达式中还是编译器错误?(更新!
- 我怎么知道编译器是否C++编译时计算表达式
- g++编译器为表达式提供<<类型错误,但在Visual Studio中工作
- 编译器是否会将这个表达式优化为一个临时常量,而不是每次迭代都解析它
- 内部编译器错误-开关表达式中的模板化转换操作符
- 编译器错误:">"标记之前的预期主表达式