std::ranges::lower_bound谓词要求疑问:为何需额外重载operator()?
std::ranges::lower_bound谓词重载问题的解决
问题根源
这不是编译器bug,是C++20 ranges库的概念约束导致的。std::ranges::lower_bound要求谓词满足std::indirect_strict_weak_order概念,这个概念会检查谓词是否能接受多种参数组合(比如元素的const/非const引用、右值等),哪怕实际运行时根本不会调用这些重载。而旧版std::lower_bound没有这么严格的检查,只要实际调用的签名匹配就行。
简洁解决办法
1. 用泛型lambda直接搞定
泛型lambda会自动适配所有需要的参数类型,不用手动写一堆重载:
auto pred = [](const auto& elem, int val) { return elem < val; }; auto it = std::ranges::lower_bound(your_range, target_val, pred);
2. 给自定义functor加模板operator()
如果必须用自定义结构体作为谓词,把operator()改成模板函数,就能匹配所有符合要求的参数:
struct MyPred { template<typename T> bool operator()(const T& elem, int val) const { return elem < val; } }; auto it = std::ranges::lower_bound(your_range, target_val, MyPred{});
3. 能用投影就别写谓词(更简洁)
如果你的比较逻辑只是取元素的某个int属性,用ranges的投影功能更省事,连谓词都不用写:
// 假设元素类型有个int成员id,或者返回int的函数get_id() auto it = std::ranges::lower_bound(your_range, target_val, {}, &YourType::id); // 或者用lambda投影 auto it = std::ranges::lower_bound(your_range, target_val, {}, [](const auto& elem) { return elem.get_some_int(); });
补充说明
这种“要求冗余重载但实际不调用”的情况是ranges库的设计初衷——通过严格的概念约束,保证代码在不同迭代器类型(比如const_iterator、非const)下都能正常编译,提升代码的通用性和健壮性。
内容的提问来源于stack exchange,提问作者dalle
相关产品推荐
相关产品推荐

