C++中使用std::set_intersection求自定义std::multiset交集的编译错误问询
代码问题排查与修正方案
先修复基础语法错误
- 结构体定义末尾缺少必须的分号:
cmp_interval结构体的闭合大括号}后面漏写了分号,这是C++新手极易触发的语法问题,会直接阻断后续编译流程。 - 比较器传参优化:原比较器采用值传递接收
Interval参数,建议修改为const左值引用传递,在不改变比较逻辑的前提下,避免无意义的对象拷贝开销。
核心报错的根因
std::set_intersection 有硬性前置要求:两个输入的元素区间必须按照完全一致的比较规则完成升序排序。
- 当没有手动给函数传入自定义比较器时,它会默认使用
std::less执行大小判断,本质是尝试对两个输入元素调用<运算符完成比较。 - 你自定义的
Interval结构体没有重载operator<,模板展开到这一步时就会触发“找不到适配const Interval的匹配operator<”的连锁报错,也就是你看到的冗长编译日志来源。 - 你的两个
multiset本身是靠传入的cmp_interval维护内部元素顺序的,但set_intersection不会自动识别容器的比较逻辑,必须手动传入和容器规则完全一致的比较器,否则不仅会编译报错,就算强行编译通过,也会因为排序规则不匹配导致交集计算结果完全错误。
自定义比较器的正确传入方式
std::set_intersection 的重载函数支持在输出迭代器参数之后,追加传入自定义比较器对象,调用格式为:
std::set_intersection( 输入区间1的起始迭代器, 输入区间1的终止迭代器, 输入区间2的起始迭代器, 输入区间2的终止迭代器, 输出迭代器, 和容器使用规则完全一致的比较器实例 );
针对当前的代码,只需要把cmp_interval{}作为最后一个参数传入即可。
修正后可直接编译运行的完整代码
#include <algorithm> #include <set> #include <iterator> struct Interval { double bottom; double top; }; struct cmp_interval { bool operator()(const Interval& a, const Interval& b) const { return a.bottom < b.bottom; } }; // 补上原代码漏掉的分号 int main() { std::multiset<Interval, cmp_interval> I1; Interval i{20, 30}; I1.insert(i); std::multiset<Interval, cmp_interval> I2; I2.insert(i); std::multiset<Interval, cmp_interval> I3; // 手动传入和容器匹配的自定义比较器 std::set_intersection( I1.begin(), I1.end(), I2.begin(), I2.end(), std::inserter(I3, I3.begin()), cmp_interval{} ); return 0; }
额外注意:你当前的比较器仅以
bottom字段作为大小判断依据,意味着只要两个Interval的bottom值相等,就会被判定为等价元素,multiset会保留所有这类等价的重复元素,set_intersection也会按照这个等价规则计算交集。如果后续需要把top字段也纳入等价判定逻辑,只需要修改operator()内的判断条件即可,不需要调整其他代码。
内容的提问来源于stack exchange,提问作者Jamāl
相关产品推荐
相关产品推荐

