mercredi 4 novembre 2015

How to use std::bind with compose2?

I would like to use a binary_function in a compose2 in C++11 with std::bind without using the boost library.

EDIT: or labmdas.

Suppose I have the following definitions:

bool GreaterThanFive(int x) { return x > 5; }

struct DivisibleByN : binary_function<int, int, bool> {
  bool operator()(int x, int n) const { return x % n == 0; }
};

Say I want to count the elements of a vector which are greater than 5 and divisible by 3. I can easily combine them with the following:

int NumBothCriteria(std::vector<int> v) {
  return std::count_if(v.begin(), v.end(),
                       __gnu_cxx::compose2(std::logical_and<bool>(),
                                           std::bind2nd(DivisibleByN(), 3),
                                           std::ref(GreaterThanFive)));
}

As bind2nd is deprecated as of C++11, I would like to move to std::bind. I haven't yet figured out why the following is not equivalent (and does not compile).

int NumBothCriteria(std::vector<int> v) {
  using namespace std::placeholders;
  return std::count_if(v.begin(), v.end(),
                       __gnu_cxx::compose2(std::logical_and<bool>(),
                                           std::bind(DivisibleByN(), _1, 3),
                                           std::ref(GreaterThanFive)));
}

It gives me the following compile error:

no type named 'argument_type' in 'std::_Bind<DivisibleByN *(std::_Placeholder<1>, int)>`
  operator()(const typename _Operation2::argument_type& __x) const
                   ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~

My intuition is that std::bind isn't doing something that std::bind2nd does, but I'm not sure how to get the argument_type typedef back.

My search came up with three questions. The first uses bind2nd, the second uses boost, and the third is for C++03. Unfortunately Effective STL still uses the std::bind2nd.

Aucun commentaire:

Enregistrer un commentaire