JobNick
JobNick

Reputation: 503

Adapt std::pair for STL algorithm lambda

Suppose I have STL container with std::pair. Is there any way to adapt pair's second for STL algorithm lambda using boost?

std::vector<std::pair<int, SomeStruct>> vec;
const auto Predicate = [](SomeStruct const& s) { ... };
auto it = std::find_if(vec.begin(), vec.end(), boost-magic(Predicate));

Upvotes: 1

Views: 313

Answers (2)

MarkusParker
MarkusParker

Reputation: 1596

Using the headers boost/range/algorithm/find_if.hpp and boost/range/adaptor/transformed.hpp you could use:

auto it = boost::find_if(vec | boost::adaptors::transformed(
  [](std::pair<int, SomeStruct>& p){ return p.second; }),Predicate); 

I am not aware of something shorter than [](std::pair<int, MyClass>& p){ return p.second; }. A raw std::get<1> does not work in this context, since it is not a functor. But my c++14-compiler also accepted the expression [](auto& p){ return std::get<1>(p); } or [](auto& p){ return p.second; }

Update: You can use boost::phoenix::at_c<0>(boost::phoenix::arg_names::arg1) to obtain a function accessing the first member of the pair and boost::lambda::bind(Predicate,boost::lambda::_1) to make Predicate work together with this function and boost::lambda's comma-operator overload to combine both:

auto it = boost::find_if(vec, (boost::lambda::bind(Predicate,boost::lambda::_1),boost::phoenix::at_c<0>(boost::phoenix::arg_names::arg1)));    

But I wouldn't call this "boost-magic", it is more like making things unnecessary complex.

Upvotes: 2

eerorika
eerorika

Reputation: 238361

No need for boost. You can simply write a lambda, or a named function object:

const auto Predicate2 = [&Predicate](std::pair<int, SomeStruct> const& s) {
    return Predicate(s.second);
};
auto it = std::find_if(vec.begin(), vec.end(), Predicate2);

Of course, if Predicate is only ever used in this one case, then it would make more sense to write it to accept a pair directly.

Upvotes: 6

Related Questions