如何让ranges::binary_search(含异构搜索)支持引用类型
问题描述
我正在尝试让自定义引用包装器支持异构搜索并符合C++ Ranges标准,编写了对应代码。传统的std算法仅需实现<和==运算符即可正常进行异构搜索,但Ranges算法的要求更严格。在实现强序比较操作后,却出现了与indirect_strict_weak_order、strict_weak_order相关的编译错误,无法理解具体原因。
问题分析
C++ Ranges算法对比较器的约束远严格于传统std算法:
- 传统算法仅要求比较操作满足基本语义(比如
<对应严格弱序),但不会在编译期做强制的概念校验; - Ranges则通过**概念(Concepts)**强制校验比较器的正确性,
indirect_strict_weak_order要求间接引用的类型间比较必须满足严格弱序,且比较器需支持异构类型组合(如引用包装器与原始类型)。
常见错误诱因包括:
- 异构比较运算符重载不完整:仅实现
MyWrapper<T> < U却未实现U < MyWrapper<T>,导致Ranges无法推导双向比较语义; - 比较操作不满足严格弱序:存在自反性(
a < a返回true)、传递性失效等问题; - 引用包装器的
operator*()返回值类型与比较器参数类型不匹配,导致indirect_strict_weak_order概念校验失败; - 自定义比较器未声明
is_transparent特性,Ranges无法识别其支持异构比较。
解决方案
可按以下步骤排查修复:
- 补全双向异构比较运算符:确保引用包装器与目标类型的双向比较均有实现,示例代码:
template <typename T, typename U> requires std::strict_weak_order<std::less<>, T, U> bool operator<(const MyWrapper<T>& lhs, const U& rhs) { return *lhs < rhs; } template <typename T, typename U> requires std::strict_weak_order<std::less<>, U, T> bool operator<(const U& lhs, const MyWrapper<T>& rhs) { return lhs < *rhs; } - 验证严格弱序合规性:确保比较操作满足三个核心条件:
- 非自反性:
a < a始终返回false; - 非对称性:若
a < b为true,则b < a必为false; - 传递性:若
a < b且b < c,则a < c必为true。
- 非自反性:
- 为自定义比较器添加
is_transparent特性:让Ranges识别其支持异构比较,示例代码:struct MyComparator { using is_transparent = void; template <typename T, typename U> bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; } }; - 检查间接引用类型:确保引用包装器的
operator*()返回const T&或T&,而非临时对象,避免间接比较时出现类型不匹配。
内容的提问来源于stack exchange,提问作者Virgileo
相关产品推荐
相关产品推荐

