Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding to a member variable

I am confused as to what boost::bind does when we bind to member variables. With binding to member function, we essentially create a function object, and then call it passing to it the arguments that are provided or delayed and substituted via placeholders.

But what does this expression do behind the scenes:

boost::bind(&std::pair::second, _1); 

What gets substituted in place of the placeholder _1?

I found this while reading this example from an article on boost::bind:

void print_string(const std::string& s) {
  std::cout << s << '\n';
}

std::map<int,std::string> my_map;
my_map[0]="Boost";
my_map[1]="Bind";

std::for_each(
  my_map.begin(),
  my_map.end(),
   boost::bind(&print_string, boost::bind(
      &std::map<int,std::string>::value_type::second,_1)));

source

like image 845
navigator Avatar asked Jul 21 '09 10:07

navigator


2 Answers

Behind the scenes it is using a member pointer and applying it to the passed in argument. It is quite complex in the context of binds, so here is a simple example of pointer to member usage:

int main()
{
   std::pair< int, int > p1 = make_pair( 1, 2 );
   std::pair< int, int > p2 = make_pair( 2, 4 );
   int std::pair<int,int>::*ptr = &std::pair<int,int>::second; // pointer to second member

   std::cout << p1.*ptr << std::endl; // 2 dereference pointer to member 
   std::cout << p2.*ptr << std::endl; // 4 dereference pointer to member
}

Behind the scenes bind is composing different calls. The resulting functor takes the dereference of std::map<>::iterator (of type std::pair< const key_type, value_type >). That is passed to the inner bind, that dereferences the member pointer, thus returning (*it).second to the outer bind that passes that value to the print_string method for the final call: print_string( (*it).second ).

(*it) is actually the _1 you asked about. All _# are placeholders, that is, the result of bind will be a functor that will take as many arguments as different placeholders exist in the order defined by the number of placeholder. In the example you gave, the resulting functor takes a single argument _1.

like image 60
David Rodríguez - dribeas Avatar answered Oct 03 '22 05:10

David Rodríguez - dribeas


boost::bind(&std::pair<U,V>::second, _1);

is functionally equivalent to

std::pair<U,V> p -> p.second

ie. it is a function (object) that maps a pair<U,V> to its second member.

like image 32
Marc Mutz - mmutz Avatar answered Oct 03 '22 04:10

Marc Mutz - mmutz