使用枚举作为常量表达式。哪个编译器是正确的?

2024-04-30

以下代码使用枚举成员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(使用前将#替换为@)

使用枚举作为常量表达式。哪个编译器是正确的? 的相关文章

随机推荐