默认飞船运算符<=>自定义返回类型:MSVC报错符合C++标准吗?
默认生成的operator<=>返回类型限制是否符合C++标准?
最新Visual Studio编译器仅允许默认生成的operator<=>返回std::strong_ordering、std::weak_ordering、std::partial_ordering这三种标准类型,这是否符合C++标准?以下通过两个示例分析:
示例1:返回void的默认operator<=>
代码实现:
struct A { void operator<=>(const A &) const = default; };
编译器表现:GCC和Clang可正常编译,但MSVC报错误C7634:'void': is not a valid comparison type; consider using 'std::strong_ordering' instead。
合法性分析
根据C20标准,默认生成的比较运算符返回类型必须是auto、bool(仅适用于operator==)或比较类别类型(即std::strong_ordering、std::weak_ordering、std::partial_ordering)。void不属于上述合法类型,因此示例1的代码不符合C标准。MSVC的报错符合标准要求,而GCC和Clang的编译通过属于未严格执行标准检查的情况。
示例2:返回自定义比较类型的默认operator<=>
代码实现:
#include <compare> struct A { int a; constexpr bool operator==(const A & r) const { return a == r.a; } constexpr int operator<=>(const A & r) const { return a - r.a; } }; static_assert(A{1} < A{2}); static_assert(A{3} >= A{2}); struct S : std::strong_ordering { constexpr S(std::strong_ordering b) : std::strong_ordering(b) {} constexpr S(int b) : std::strong_ordering(b <=> 0) {} }; struct B : A { int b; S operator<=>(const B &) const = default; }; static_assert(B{{1},2} < B{{2},1}); static_assert(B{{1},1} <= B{{1},1}); static_assert(B{{3},2} > B{{2},3}); static_assert(B{{2},2} == B{{2},2});
编译器表现:GCC和Clang可正常编译,MSVC报错误C2280并触发内部编译器崩溃。
合法性分析
C标准允许比较类别类型的派生类作为默认operator<=>的返回类型,因为派生类继承了基类的比较语义,属于合法的比较类别范畴。示例2中的S继承自std::strong_ordering,完全符合标准要求。MSVC的报错及内部崩溃属于编译器实现缺陷,不符合C标准的规定。
总结
- 示例1代码不合法,MSVC的报错符合标准;
- 示例2代码合法,MSVC的报错属于实现问题,不符合标准。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

