c++ - 将默认赋值运算符声明为 constexpr : which compiler is right?

标签 c++ language-lawyer c++17 constexpr

考虑

struct A1 {
    constexpr A1& operator=(const A1&) = default;
    ~A1() {}
};
struct A2 {
    constexpr A2& operator=(const A2&) = default;
    ~A2() = default;
};
struct A3 {
    ~A3() = default;
    constexpr A3& operator=(const A3&) = default;
};

GCC 和 MSVC 接受所有三个结构。 Clang 拒绝 A1A2(但接受 A3),并带有以下错误消息:

<source>:2:5: error: defaulted definition of copy assignment operator is not constexpr
    constexpr A1& operator=(const A1&) = default;
    ^
<source>:6:5: error: defaulted definition of copy assignment operator is not constexpr
    constexpr A2& operator=(const A2&) = default;
    ^
2 errors generated.

( live demo )

哪个编译器是正确的,为什么?

最佳答案

我认为这三个编译器都错了。

[dcl.fct.def.default]/3说:

An explicitly-defaulted function that is not defined as deleted may be declared constexpr or consteval only if it would have been implicitly declared as constexpr. If a function is explicitly defaulted on its first declaration, it is implicitly considered to be constexpr if the implicit declaration would be.

复制赋值运算符何时隐式声明constexpr[class.copy.assign]/10 :

The implicitly-defined copy/move assignment operator is constexpr if

  • X is a literal type, and
  • [...]

文字类型在哪里,来自 [basic.types]/10 :

A type is a literal type if it is:

  • [...]
  • a possibly cv-qualified class type that has all of the following properties:

    • it has a trivial destructor,
    • [...]

A1 没有普通的析构函数,因此它的隐式复制赋值运算符不是 constexpr。因此,复制赋值运算符格式不正确(gcc 和 msvc 错误接受)。

另外两个没问题,拒绝A2是个clang bug。


注意我引用的 [dcl.fct.def.default] 的最后一点。如果您明确默认,您实际上不必添加 constexpr 。在可能的情况下,这将是隐含的 constexpr

关于c++ - 将默认赋值运算符声明为 constexpr : which compiler is right?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55182242/

相关文章:

c++ - "constexpr if"vs "if"优化 - 为什么需要 "constexpr"?

c++ - enable_if 函数在不应该定义的时候定义

python 2 - 为什么 'with' 在嵌入式 c 代码中的行为不同?

c++ - 在这种情况下我可以忽略 C4251 警告吗?

c++ - 模板中的字符串文字 - 编译器的不同行为

C++-为什么这里需要 'template'关键字?

c++ - ghdl 缺少 util.misc_conv_pkg ubuntu 14.04

c++ - 从特定专业继承时可访问模板基类?

c++ - 如何将模板 lambda 传递给函数并将其与不同类型一起使用

c++ - 将包含重音字符的 UTF-8 字符串转换为 UTF-16