C++20三路比较运算符返回类型的比较运算符重载行为疑问
结论
GCC和Clang的行为符合C++20标准要求,MSVC的实现存在已知缺陷。
核心规则依据
比较运算符重写规则
C++20标准明确规定:如果类定义了可访问的operator<=>,那么a < b这类关系运算符会被自动重写为(a <=> b) < 0,重写后的表达式会进入正常的重载决议流程。MSVC对#1代码行报error C2088: '<': illegal for struct属于实现错误,未正确支持比较运算符的重写逻辑。0字面量的匹配规则
整型字面量0属于空指针常量,可以隐式转换为std::nullptr_t,且该转换属于精确匹配等级,因此代码中定义的void operator< (std::strong_ordering, std::nullptr_t)是合法的可行重载候选。重载决议的优先级判定
标准库中std::strong_ordering的比较运算符属于隐藏友元,仅能通过ADL(参数依赖查找)找到,其第二个参数是实现定义的、仅能接受0字面量的专用类型。GCC/Clang的实现中,0到std::nullptr_t的转换序列优先级高于到标准库专用类型的转换序列,因此会优先选择自定义的重载,不会产生歧义。MSVC的标准库实现中,该专用类型为整型,导致0到整型和std::nullptr_t的转换等级相同,因此误报歧义错误。
使用提示
这种重载行为虽然符合标准语法,但不推荐在生产代码中使用:
- 标准明确要求
std::strong_ordering与0的比较运算符应当返回bool类型,自定义重载返回void违反了类型的约定语义,会导致代码可读性和可移植性大幅下降。 - 不同编译器的标准库实现细节不同,这类依赖实现优先级的代码无法保证跨编译器行为一致。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

