You need to enable JavaScript to run this app. C++中使用std::set_intersection求自定义std::multiset交集的编译错误问询
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 08:36:05