考虑
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 拒绝 A1
和 A2
(但接受 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 )
哪个编译器是正确的,为什么?
最佳答案
我认为这三个编译器都错了。
An explicitly-defaulted function that is not defined as deleted may be declared
constexpr
orconsteval
only if it would have been implicitly declared asconstexpr
. If a function is explicitly defaulted on its first declaration, it is implicitly considered to beconstexpr
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/