class A // Just some class.
{
void foo() {} // Member function I want to call with std::for_each().
};
std::map<int, A> con;
//...
std::for_each(con.begin(), con.end(), std::mem_fun_ref(A::foo)); // Won't work! The container contains std::pair<int, A> elements, not A elements!
Adapting STL Algorithms to Associative Containers (std::pair Elements)
Is there a clean way to adapt the standard STL algorithms to std::pair elements? I'm frustrated with not being able to use common algorithms with associative containers like std::map. For example, let's say I have a map of some class A with a method I want to call on each.
So, is there a way around this problem? Obviously, std::for_each() isn't the only algorithm that doesn't work well with associative containers. Some offer member function versions, but the selection there is extremely limited.
Thanks!
One way:
typedef std::map<int, A> MyMap;void do_foo(MyMap::value_type & vt) { vt.second.foo();}std::for_each(con.begin(), con.end(), &do_foo);
Most(if not all) of the algorithms take a function as a last parameter so that you can access elements no matter how they are stored.(That way you can store pointers in a container and still find it useful)
as in:
int equator(pair<int,a> first, pair<int,a> second)
{
return first.fst == second.fst
}
find(vector.begin,vector.end,equator);
(I just made that up off the top of my head so it more than likely won't compile.)
as in:
int equator(pair<int,a> first, pair<int,a> second)
{
return first.fst == second.fst
}
find(vector.begin,vector.end,equator);
(I just made that up off the top of my head so it more than likely won't compile.)
or you can use boost.bind
std::for_each( con.begin(), con.end(), boost::bind(&A::foo, boost::bind( &std::map<int, A>::value_type::second, _1)));
Ah, thanks, ChaosEngine! That's exactly what I was just trying to do but I didn't get the syntax right!
Also, thanks for the function-based examples; I tend to forget that the algorithms usually just take functors or function pointers, so you can pretty much do anything you need.
Also, thanks for the function-based examples; I tend to forget that the algorithms usually just take functors or function pointers, so you can pretty much do anything you need.
I am sure I saw a "select2nd" functor once which did this job, and was a massive amount cleaner than that grotesque boost::bind monstrosity, but I can't find it.
SGI STL contains select1nd and select2nd as a non-standard extension. They shouldn't be too hard to implement manually:
It shouldn't be too difficult to generalize that for arbitrary boost/tr1/std::tuples, either.
template <typename Pair>struct select1st : std::unary_function<typename Pair::first_type, Pair>{ result_type& operator ()(Pair& pair) { return pair.first; } const result_type& operator ()(const Pair& pair) { return pair.first; }}template <typename Pair>struct select2nd : std::unary_function<typename Pair::second_type, Pair>{ result_type& operator ()(Pair& pair) { return pair.second; } const result_type& operator ()(const Pair& pair) { return pair.second; }}
It shouldn't be too difficult to generalize that for arbitrary boost/tr1/std::tuples, either.
You'd think that since there's already a special case for 2-tuples (ie. pairs), that they'd have standardised such functors to extract those values too. Ah well. Thanks for the implementation. :)
TR1 does specify the template free function get_element, which gets an indexed element from a tuple and is also specialised to get an element from a std::pair, i.e. get_element< 0 >(pair);
Σnigma
Σnigma
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement