Clang抱怨ConstexPR函数在switch语句的情况下

clang complains about constexpr function in case for switch statement

本文关键字:语句 情况下 switch 抱怨 ConstexPR 函数 Clang      更新时间:2023-10-16
struct X
    {
    enum class E
    {
        A,B
    };
    static constexpr X A()
    {
        return X{E::A};
    }
    static constexpr X B()
    {
        return X{E::B};
    }
    constexpr operator E() const
    {
        return a;
    }
    E a;
};
template <typename T>
struct Y
{
    void f()
    {
        // without this line clang errs
        // const auto & x = this->x;
        switch(x)
        {
            case X::A():
            case X::B():
            default: return;
        }
    }
    X x = X::A();
};
int main()
{
    Y<int>{}.f();
}

如果代码段中没有标记的行,则 clang 会给出以下错误:

错误:大小写值不是常量表达式大小写

X::B((:

但是我尝试了 gcc,它编译得很好。有人知道 gcc 是宽容还是 clang 有一些错误?

参见 godbolt (clang 8.0.0(: https://godbolt.org/z/ETe5WQ但是(gcc 8.3(编译得很好(也在godbolt上(,并尝试了其他版本的gcc,也很好

更新:

打开了一个错误

Clang (8.0.0( 这里有一个错误。

如果您编写constexpr auto A = X::A();并在 switch 语句中使用 case A:,则会收到相同的编译错误(表示 A 不是常量表达式(。

但是,如果删除这些大小写,它会编译良好(这意味着A有效的constexpr =>与前一个错误相矛盾(。

此外,switch(x)失败而switch(this->x)成功。由于x == this->x在您的情况下,这绝对是一个错误。

正如chtz所提到的,clang(5/6(似乎工作得很好。这不是一个论点,而是一个明显的倒退。

更新:正如OP所提到的,他们提交了错误报告。

似乎 clang 无法确定 switch(x) 是枚举X::E上的开关。

如果将显式强制转换添加到X::E(static_cast或 C 样式或其他样式(,则代码无需更改即可编译。

仅当您的类是template时,才会发生这种情况。

使用switch(this->x)也有效。

因为每当x是类的成员时,x也只是this->x的另一个名字,即使在template中,这也必须是一个叮当错误。

有关如何对非枚举/整型进行切换的规则很有趣,因为它们依赖于switch表达式中任何枚举或整型类型的未指定强制转换运算符的存在,然后在case表达式中调用相同的强制转换。

相关文章: