Передача предикатов std algos по ссылке в C ++ - PullRequest
9 голосов
/ 29 ноября 2011

Я пытаюсь удалить элементы из 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 ]

15 голосов
/ 29 ноября 2011

Передайте справочную упаковку, доступную от <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));
2 голосов
/ 29 ноября 2011

Функторы, передаваемые в алгоритмы, можно копировать в алгоритм неограниченное количество раз, поэтому вы не можете сохранять состояние непосредственно в функторе.С другой стороны, вы можете сохранить состояние вне функтора, используя указатель или ссылку на некоторую внешнюю структуру состояний.

...