在C ++中通过引用传递std algos谓词

时间:2011-11-29 15:28:18

标签: c++ algorithm pass-by-reference std predicate

我正在尝试从std::list中删除元素,并保留一些已删除元素的统计信息。

为了做到这一点,我使用列表中的remove_if函数,我有一个谓词。我想用这个谓词来收集统计数据。以下是谓词的代码:

  class TestPredicate
  {
  private:
    int limit_;

  public:
    int sum;
    int count;
    TestPredicate(int limit) : limit_(limit), sum(0), count(0) {}

    bool operator() (int value) 
    {
      if (value >= limit_)
      {
        sum += value;
        ++count;       // Part where I gather the stats
        return true;
      }
      else
        return false;
    }
  };

以下是算法的代码:

std::list < int > container;
container.push_back(11);
TestPredicate pred(10);
container.remove_if(pred)
assert(pred.count == 1);

不幸的是,断言是错误的,因为谓词是按值传递的。有没有办法强制它通过引用传递?

2 个答案:

答案 0 :(得分:15)

传递<functional>提供的参考包装:

container.remove_if(std::ref(pred));

如果你只有C ++ 98/03,但你的编译器有TR1,如果对你的谓词进行小修改,你可以使用<tr1/functional>std::tr1::ref

#include <tr1/functional>

class TestPredicate : public std::unary_function<int, bool>
{                 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ...
}

container.remove_if(std::tr1::ref(pred));

如果所有其他方法都失败了,那么您可以相对轻松地破解手动解决方案:

struct predref
{
  TestPredicate & p;
  bool operator()(int n) { return p(n); }
  predref(TestPredicate & r) : p(r) { }
};

container.remove_if(predref(pred));

答案 1 :(得分:2)

传递给算法的仿函数可以在算法内复制不确定的次数,因此您无法直接在仿函数中存储状态。另一方面,您可以通过使用指针或对某些外部状态结构的引用来将状态存储在仿函数之外。