【问题标题】:C++ STL set with custom comparator使用自定义比较器设置的 C++ STL
【发布时间】:2021-03-17 18:42:30
【问题描述】:

对于 C++ STL set,我需要自定义比较,但我的代码存在严重问题。使用 Visual Studio 2019 编译失败。第一个错误是(在 xutility 中)“错误 C2672: 'operator __surrogate_func': 找不到匹配的重载函数”。

代码如下:

#include <set>

struct P
{
    char a;
    char b;
    char c;
};

class PSortingCriterion
{
public:
    bool operator() (const P &p1, const P &p2) const
    {
        if(p1.a != p2.a)
            return p1.a < p2.a;
        else if(p1.b != p2.b)
            return p1.b < p2.b;
        else if(p1.c != p2.c)
            return p1.c < p2.c;
        else
            return false; // p1 == p2
    }
};

std::set<P, PSortingCriterion> s1, s2, diff;

void F(void)
{
    if(s1 != s2) // errors are all due to this statement; no errors if it's removed
    {
    }
}

更新:按照 Igor Tandetnik 的建议,我修改了代码,但仍然无法编译(与上述相同的错误)。

新代码:

#include <set>
#include <algorithm>
#include <iterator>

struct P
{
    char a;
    char b;
    char c;
};

class PSortingCriterion
{
public:
    bool operator() (const P &p1, const P &p2) const
    {
        if(p1.a != p2.a)
            return p1.a < p2.a;
        else if(p1.b != p2.b)
            return p1.b < p2.b;
        else if(p1.c != p2.c)
            return p1.c < p2.c;
        else
            return false; // p1 == p2
    }
};

std::set<P, PSortingCriterion> s1, s2, diff;

void F(void)
{
    set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(diff, diff.begin()));
}


   

【问题讨论】:

    标签: stl set comparator


    【解决方案1】:

    要比较两个集合,您需要比较元素。见CppReference。但是您没有提供任何方法来比较两个 P 类型的对象是否相等。

    如果你添加:

    bool operator== (const P& p1, const P& p2) {
       return p1.a == p2.a && p1.b == p2.b && p1.c == p2.c;
    }
    

    然后您的代码将编译。

    【讨论】:

    • 您的建议确实有效(谢谢),但它不能满足我的需要。我需要能够使用set_difference。如果我添加行 if(s1&lt;s2),我会得到我最初显示的错误,尽管我提供了一个仿函数来进行比较。
    • @Woody20 set&lt;T, Compare&gt;::operator&lt; 被记录为忽略 Compare,并使用小于 &lt; 运算符来比较集合的元素。但是你没有提供一个。如果你想使用set_difference,那么一定要使用它——调用将比较器作为参数的重载。
    • @Igor Tandetnik 我试过你的建议,但还是有问题。我已经发布了完整的代码作为原始问题的补充。
    • “使用set_difference 的重载需要比较器”的哪一部分不清楚?让它set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(diff, diff.begin()), PSortingCriterion{});
    • 我按照 Josuttis 的书 10.1.1 Function Objects as Sorting Criteria 中的示例,他说我所做的定义的排序标准是一种类型,可以用作模板参数为集合。我假设这意味着当我定义 P 时,PSortingCriterion 定义了 &lt;,将用作默认值。
    【解决方案2】:

    这是一个重载 ==!= 运算符的简单示例(我认为这就是你想要做的事情?)

    
    #include<set>
    #include<iostream>
    
    struct P {
        char a;
        char b;
        char c;
        bool operator==(const P &p2) const {
          return this->a == p2.a && this->b == p2.b && this->c == p2.c;
        }
        bool operator!=(const P &p2) const {
          return this->a != p2.a || this->b != p2.b || this->c != p2.c;
        }
    };
    
    void EqualExample(void) {
      P s1;
      s1.a = 'a';
      s1.b = 'b';
      s1.c = 'c';
      P s2;
      s2.a = 'a';
      s2.b = 'b';
      s2.c = 'c';
      if(s1 != s2){
        std::cout << "Not Equal" << std::endl;
      } else {
        std::cout << "Equal" << std::endl;
      }
    }
    
    void NotEqualExample(void) {
      P s1;
      s1.a = 'a';
      s1.b = 'b';
      s1.c = 'c';
      P s2;
      s2.a = 'a';
      s2.b = 'b';
      s2.c = 'd';
      if(s1 != s2){
        std::cout << "Not Equal" << std::endl;
      } else {
        std::cout << "Equal" << std::endl;
      }
    }
    
    int main () {
      EqualExample();
      NotEqualExample();
    }
    

    【讨论】:

    • 你可以去掉 iostream 如果你不需要它来做其他事情,我只是用它来打印
    • 查看我对 Marshall Chow 的回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    相关资源
    最近更新 更多