Jump to content
  • Advertisement
Sign in to follow this  

Adapting STL Algorithms to Associative Containers (std::pair Elements)

This topic is 3784 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.
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!
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!

Share this post


Link to post
Share on other sites
Advertisement
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);

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
SGI STL contains select1nd and select2nd as a non-standard extension. They shouldn't be too hard to implement manually:


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.

Share this post


Link to post
Share on other sites
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. :)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!