首页 > 解决方案 > 带有自定义设置比较器的 set_intersection

问题描述

当我将 std::set_intersection 函数与具有自定义比较器的集合一起使用时,我没有得到预期的结果。以下代码输出 {5,9,7} intersect {9} 为空集。但是,如果我只使用普通比较器,我会得到 {9}。

#include <iostream>
#include <cstdlib>
#include <set>

using namespace std;
auto cmp = [](int* a, int* b) { return a < b; };
using stupid_set = set<int*, decltype(cmp)>;
int main() {
    int* n5 = new int(5);
    int* n9 = new int(9);
    int* n7 = new int(7);
    stupid_set s0 {n5, n9, n7};
    stupid_set s1 {n9};
    stupid_set i;
    for (auto s:s0) {
        cout << "s0:" << *s << endl;
    }
    for (auto s:s1) {
        cout << "s1:" << *s << endl;
    }
    set_intersection(s0.begin(), s0.end(), s1.begin(), s1.end(), std::inserter(i, i.begin()));
    for (auto x : i) {
        cout << "Int=" << *x << endl;
    }
}

标签: c++c++11

解决方案


您的代码存在多个问题,但核心问题是您将自定义比较器用于集合,而不是用于std::set_intersection函数调用。此函数还需要比较元素,当然,必须将它们与相同的比较器进行比较。

利用:

struct cmp 
{
  bool operator()(int* a, int* b) const { return *a < *b; };
};

using stupid_set = set<int*, cmp>;

set_intersection(
 s0.begin(), s0.end(),
 s1.begin(), s1.end(),
 std::inserter(i, i.begin()),
 cmp{}  // custom comparator used for sets
);

整个现场演示在这里:https ://godbolt.org/z/OAr3xV 。


请注意,如果您省略比较器,std::set_intersectionoperator<用于设置元素,并且此操作对于指针通常是未定义的

如果您真的想比较指针而不是那里指向的整数值,则需要使用std::less,因为这甚至定义了一般指针的顺序:

struct cmp 
{
  bool operator()(int* a, int* b) const { return std::less<int*>{}(a, b); };
};

同样,您还需要将此比较器传递给std::set_intersection

现场演示:https ://godbolt.org/z/tLdfqn 。


推荐阅读