Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ function object to return `p->first` and `p->second`

Tags:

c++

stl

boost

Is there a builtin function object that returns p->first and p->second, so that I can happily write

transform(m.begin(),m.end(),back_inserter(keys),get_first);
transform(m.begin(),m.end(),back_inserter(vals),get_second);

STL-based solution is the best, boost solution is second best.

Yeah, I know boost::lambda, I don't want to start using it.

like image 338
Elazar Leibovich Avatar asked Mar 07 '11 09:03

Elazar Leibovich


3 Answers

There are nonstandard extensions to g++ and SGI called select1st and select2nd. So there's probably nothing in the STL for that.

Boost's bind can also do that, give it a pointer to the correct member function

boost::bind(&std::map<string,string>::value_type::second,_1)
like image 70
Elazar Leibovich Avatar answered Oct 24 '22 01:10

Elazar Leibovich


We can easily write a select1st and select2nd:

struct select1st
{
   template< typename K, typename V >
   const K& operator()( std::pair<K,V> const& p ) const
   {
       return p.first;
   }
};

struct select2nd
{
   template< typename K, typename V >
   const V& operator()( std::pair<K,V> const& p ) const
   {
       return p.second;
   }
};

Here is an alternative, actually more flexible version:

struct select1st
{
   template< typename P >
   typename P::first_type const& operator()( P const& p ) const
   {
       return p.first;
   }
};

struct select2nd
{
   template< typename P >
   typename P::second_type const& operator()( P const& p ) const
   {
       return p.second;
   }
};

subsequently:

transform(m.begin(),m.end(),back_inserter(keys), select1st());
transform(m.begin(),m.end(),back_inserter(vals), select2nd());
like image 5
CashCow Avatar answered Oct 24 '22 00:10

CashCow


If you can use C++0x you can either use real lambdas since G++ 4.5 or you can use the new tuple-library which is fully compatible with std::pairs. Then you could use std::get<0> for first and std::get<1> for second.

If you are bound to C++98 you can use std::tr1::tuple instead of std::pair, as in TR1 get doesn't work with std::pair.

Also you can use bind from TR1 (tr1/functional) like Elazar described it.

like image 2
filmor Avatar answered Oct 23 '22 23:10

filmor