设置的自定义比较器,不重载operator(),std :: less,std :: greater

时间:2019-05-31 19:32:02

标签: c++ c++11 lambda

我想要以下代码的自定义比较器。但是,我不能重载operator(),std :: less,std :: greater。我尝试使用lambdas实现此目的,但gcc不允许我将auto用作非静态成员。还有其他方法可以做到这一点吗?

#include <iostream>
#include <map>
#include <set>

class Test {
  public:

    // bool operator () (const int lhs, const int rhs) {
    //     return lhs > rhs;
    // };


    using list = std::multiset<int  /*, Test*/>;
    std::map<const char*, list> scripts;
};

int main() {
  Test t;

  t.scripts["Linux"].insert(5);
  t.scripts["Linux"].insert(8);
  t.scripts["Linux"].insert(0);

  for(auto a: t.scripts["Linux"]) {
    std::cout << a << std::endl;
  }

    std::cout << "end";
}

编辑: 使用lambdas

class Test {
  public:
    auto compare = [] (const int a, const int b) { return a < b;}
    using list = std::multiset<int, compare>;    //here
    std::map<const char*, list> scripts;
};

错误: 'auto' not allowed in non-static class member auto compare = [] (const int a, const int b) { return a < b;}

3 个答案:

答案 0 :(得分:0)

您可以在构造函数中使用比较函数的函数指针:

main.cpp

#include <iostream>
#include <set>

using compType=bool(*)(int lhs, int rhs);

bool custom_compare_function(int lhs, int rhs)
{
    return lhs>rhs;
}


using list = std::multiset<int,compType>;
int main() {
    list l(&custom_compare_function);
    l.insert(1);
    l.insert(4);
    l.insert(2);
    for (auto& item: l) std::cout<<item<<std::endl;
}

产生输出

$ g++ main.cpp 
$ ./a.out 
4
2
1

答案 1 :(得分:0)

  

我想要以下代码的自定义比较器。但是,我不能   operator()std::lessstd::greater超载。

我假设您不允许重载operator()的{​​{1}},但可能是其他类的重载。如果是这样,请创建一个内部Test函数,该函数重载private,并且可能是别名operator()

的一部分
using list = std::multiset<int, Compare>;

答案 2 :(得分:0)

即使您可以按照自己的方式定义lambda,您的方法也存在问题。看看the multiset declaration

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class multiset;

注意每个模板参数的类型(使用class关键字)。现在看看如何尝试定义列表:

using list = std::multiset<int, compare>;
                            ^      ^
                          type   value

第一个参数不错,但是第二个参数不匹配。 Compare参数必须是类型,而不是对象。解决这种情况的一种通用方法是将compare替换为decltype(compare),但这似乎不是您想要的(而且对于lambda类型来说是有问题的)。您似乎希望默认构造的list使用compare而不是仅使用相同类型的默认构造对象。

因此,您需要一个类,该类的默认构造对象以给出所需顺序的方式实现operator()。由于我们正在处理int,因此标准库为此提供了一些现成的类型,即std::lessstd::greater

using list = std::multiset<int, std::greater<int>>;
  

但是,我无法重载operator(),std :: less,std :: greater。

嗯...这表明示例代码可能已经过简化,因为不需要重载。好的,让我们假设列表是某种难以处理的类型,例如:

class I { /* Internals not important for this example. */ };
using list = std::multiset<I, ???>;

如果允许您修改I,则最简单的方法可能是为类型operator>的对象定义operator<(或I)。由于std::greater(或std::less)使用此运算符,因此您可以从标准模板中获得所需的顺序,而不会使其过载。

如果不允许您修改I,那么我认为您只需要编写自己的function object,因为这是lambda不足的一种情况。幸运的是,实现函数对象的类很容易编写。在其他情况下,lambda取代了lambda,主要是因为lambda语法往往更方便。

struct CompareI {
    bool operator() (const I & lhs, const I & rhs) const { return /* fill this in */; }
};
using list = std::multiset<I, CompareI>;

尽管这定义了operator(),但这并不是重载。因此它应该满足您的要求。