std::equality_comparable_with对自定义operator==类型不生效是什么原因
核心原因
std::equality_comparable_with<T, U> 的约束远不止「T和U可以双向调用==返回bool」,它额外强制了以下要求:
T和U各自都要满足std::equality_comparable,也就是可以和自身类型做相等比较T和U必须满足std::common_reference_with,即两个类型存在公共的引用类型,且该公共类型本身也支持相等比较- 双向比较的结果必须与「将两个对象都转换为公共引用类型后再比较」的结果完全一致,保证比较语义的统一性
你提供的代码首先缺少<concepts>头文件(std::equality_comparable_with定义在此头中),更关键的是A和std::string_view没有默认的公共引用类型,因此约束不满足。而std::string和std::string_view能通过断言,是因为标准库已经为二者特化了std::common_reference,公共类型为std::string_view,且比较语义符合要求。
修复方案
如果你确实需要满足std::equality_comparable_with的完整语义,可以做以下修改:
- 补充
A类型自身的相等比较运算符,满足std::equality_comparable<A>的要求 - 为
A和std::string_view显式特化std::common_reference,指定二者的公共引用类型 - 确保比较语义和公共类型的比较逻辑一致
修复后的代码示例:
#include <string_view> #include <concepts> struct A { int n; }; // 实现A自身的相等比较 bool operator==(const A&, const A&) = default; // 实现跨类型比较 bool operator==(const A& a, const std::string_view s) { return a.n == s.size(); } // 显式特化common_reference,指定公共类型为std::string_view template<> struct std::common_reference<const A&, const std::string_view&> { using type = std::string_view; }; // 特化反向顺序的版本 template<> struct std::common_reference<const std::string_view&, const A&> { using type = std::string_view; }; // 静态断言现在可以正常通过 static_assert(std::equality_comparable_with<A, std::string_view>);
轻量替代方案
如果你不需要std::equality_comparable_with的严格语义,只是想检测两个类型是否可以双向做相等比较,可以自定义轻量概念,避免额外的公共引用类型约束:
#include <concepts> #include <string_view> struct A { int n; }; bool operator==(const A& a, const std::string_view s) { return a.n == s.size(); } template<typename T, typename U> concept can_equality_compare = requires(const T& t, const U& u) { { t == u } -> std::convertible_to<bool>; { u == t } -> std::convertible_to<bool>; }; static_assert(can_equality_compare<A, std::string_view>);
C++20的运算符重写机制会自动把string_view == A的调用重写为你定义的A == string_view版本,无需手动实现反向参数的运算符。
内容的提问来源于stack exchange,提问作者aradarbel10
相关产品推荐
相关产品推荐

