std::multiset 交集编译错误

问题描述

我正在尝试使用 std::set_intersection 函数找到 2 个多组对象的交集。

#include <algorithm>
#include <set>


struct Interval
{
  double bottom;
  double top;
};

struct cmp_interval
{
  bool operator()(Interval a,Interval b) const
  {
    return a.bottom < b.bottom;
  }

}

int main()
{
  std::multiset<Interval,cmp_interval> I1;
  Interval i;
  i.bottom = 20;
  i.top = 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()));
  return 0;
}

当我尝试编译它时,我得到了一页我无法正确理解的详细错误。尽管我确实了解一些基本概念,但我仍然是 C++ 的新手。下面是生成错误日志,

Starting build...
/usr/bin/g++ -g /home/jamal/Documents/daa_assignment_1/measure.cpp -o /home/jamal/Documents/daa_assignment_1/measure
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,from /usr/include/c++/9/bits/char_traits.h:39,from /usr/include/c++/9/ios:40,from /usr/include/c++/9/ostream:38,from /usr/include/c++/9/iostream:39,from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h: In instantiation of ‘constexpr bool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1,_Iterator2) const [with _Iterator1 = std::_Rb_tree_const_iterator<Interval>; _Iterator2 = std::_Rb_tree_const_iterator<Interval>]’:
/usr/include/c++/9/bits/stl_algo.h:5252:12:   required from ‘_OutputIterator std::__set_intersection(_InputIterator1,_InputIterator1,_InputIterator2,_OutputIterator,_Compare) [with _InputIterator1 = std::_Rb_tree_const_iterator<Interval>; _InputIterator2 = std::_Rb_tree_const_iterator<Interval>; _OutputIterator = std::insert_iterator<std::multiset<Interval,cmp_interval> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/9/bits/stl_algo.h:5307:48:   required from ‘_OIter std::set_intersection(_IIter1,_IIter1,_IIter2,_OIter) [with _IIter1 = std::_Rb_tree_const_iterator<Interval>; _IIter2 = std::_Rb_tree_const_iterator<Interval>; _OIter = std::insert_iterator<std::multiset<Interval,cmp_interval> >]’
/home/jamal/Documents/daa_assignment_1/measure.cpp:338:100:   required from here
/usr/include/c++/9/bits/predefined_ops.h:43:23: error: no match for ‘operator<’ (operand types are ‘const Interval’ and ‘const Interval’)
   43 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/stl_iterator.h:915:5: note: candidate: ‘template<class _IteratorL,class _IteratorR,class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL,_Container>&,const __gnu_cxx::__normal_iterator<_IteratorR,_Container>&)’
  915 |     operator<(const __normal_iterator<_IteratorL,_Container>& __lhs,|     ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:915:5: note:   template argument deduction/substitution Failed:
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h:43:23: note:   ‘const Interval’ is not derived from ‘const __gnu_cxx::__normal_iterator<_IteratorL,_Container>’
   43 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/stl_iterator.h:922:5: note: candidate: ‘template<class _Iterator,class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator,const __gnu_cxx::__normal_iterator<_Iterator,_Container>&)’
  922 |     operator<(const __normal_iterator<_Iterator,|     ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:922:5: note:   template argument deduction/substitution Failed:
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h:43:23: note:   ‘const Interval’ is not derived from ‘const __gnu_cxx::__normal_iterator<_Iterator,_Container>’
   43 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~

Build finished with error(s).
The terminal process Failed to launch (exit code: -1).



任何帮助将不胜感激。谢谢。

更新:错误日志中,我看到还有一个可选参数需要传递给 std::set_intersection 以用于自定义比较器。

/usr/include/c++/9/bits/stl_algo.h:5252:12:   required from ‘_OutputIterator std::__set_intersection(_InputIterator1,cmp_interval> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’

_Compare 参数看起来是认的 __gnu_cxx::__ops::_Iter_less_iter。我想使用我在那里制作的比较器类(cmp_interval),但它不接受类。

解决方法

std::multiset<Interval,cmp_interval> I3;

在这里,您将比较器的类型指定为类型模板参数。实际的比较器对象是在 multiset 的构造函数中创建的。现在您想将一个类似的 object 传递给 std::set_intersection 函数。使用:

std::set_intersection(I1.begin(),I1.end(),I2.begin(),I2.end(),std::inserter(I3,I3.begin()),cmp_interval());

cmp_interval() 中的空括号表示:未命名的默认构造对象。您也可以使用 cmp_interval{},因为 C++11。