【问题标题】:About modifying the parameter of a functor关于修改函子的参数
【发布时间】:2014-04-08 14:31:10
【问题描述】:

我有以下字符串对象的比较器

struct Comparator{

  int x;

  bool operator() (string a, string b) {

    int i = 1;

    if(a < b) {
      i = -1;
    } 

    i*= x;

    if(i==-1) {
      return true;
    } 

    return false;

  }

};

如你所见,它有一个参数x。为=1时字符串比较正常,=-1时反相比较。

当在sort 之类的方法中为vector 元素使用它时,我可以用正确的x 给这个比较器的对象实例,但是当我想把这个比较器给像set 这样的模板类时,我需要给一个类而不是一个对象实例。所以我看到的唯一解决方案是将x 设为静态。有没有更好的解决方案?

这是我想使用此比较器的主要示例:

int main(int argc, char** argv)
{

  vector<string> vec;

  vec.push_back("c");
  vec.push_back("a");
  vec.push_back("b");

  Comparator comp;

  comp.x = 1; // for normal comparison
  comp.x = -1; // for inverse comparison

  sort(vec.begin(),vec.end(), comp); // here I can give the functor instance

  for(vector<string>::iterator it = vec.begin() ; it != vec.end(); it++)
  {
    cout << *it << endl;
  }

  set<string, Comparator> ss; // but here I must give the name of the functor class

  ss.insert("c");
  ss.insert("a");
  ss.insert("b");

  for(set<string>::iterator it = ss.begin() ; it != ss.end(); it++)
  {
    cout << *it << endl;
  }

  return 0;
}

【问题讨论】:

    标签: c++ templates stl functor


    【解决方案1】:

    set 的所有相关构造函数也采用Comp 类的实例。

     set<string, Comparator> ss(Comparator(-1)); 
    

    现在您只需要 Comparator 的构造函数,用适当的值初始化其成员 x

    也就是说,标准库已经为此目的提供了一个比较器类:

    set<string, std::greater<std::string> > ss;
    

    【讨论】:

    • 谢谢。这是我一直在寻找的干净方式。关于您的第二句话,我的仿函数有点复杂,但我只是将其简化为问题的二进制情况。但是我不知道 std::greater :) 所以再次感谢
    • 我只是注意到每次我需要声明一个集合时都会创建一个新对象。而且我只想对使用相同比较器实例的所有集合使用一个对象。那么有没有更好的办法呢?
    • 设置容器包含比较器的副本,所以不是真的。无论如何,这有什么问题?包含单个 int 的结构体复制起来很便宜,就像函数指针一样(如果你选择切换到那个)。
    • 问题在于它不仅仅是一个int,甚至不是一个参数。我们的应用程序对性能至关重要。为什么容器集需要制作副本?如果 set ss(comp) 只包含对 comp 的引用,那就太好了
    • 我需要去阅读你提到的那个“函数指针”,看看如何将它应用到这个。这可能是我需要的解决方案...
    【解决方案2】:

    那行不通:a

    你可以使用 std::string::compare:

    bool operator() (const std::string& a, const std::string& b) {
        int result = a.compare(b) * x;
        return result < 0;
    }
    

    【讨论】:

    • 是的,我同意,但我只是做了一个简单的例子来解释我的问题。
    猜你喜欢
    • 2019-07-15
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多