views:

269

answers:

4

I am having trouble figuring out mem_fun_ref. I have to admit, I usually use functors for this kind of thing, since they can be inlined for speed and profit. However, this code is not going to be a bottleneck and so I wanted to try this thing.

Here is an example of what I want to do. I know there are other ways to do it. I don't want to use copy, I don't want to use range member functions, I don't want to use a back_inserter. I specifically want to use mem_fun_ref. This is just a simple example, the real case is much more complicated. That said, I really don't know why this is wrong, but I am not familiar with mem_fun_ref or mem_fun.

Here's what I want to work:

#include <list>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

int main()
{
    list<int> a;
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    vector<int> b;

    // should work like magic!
    for_each(a.begin(), a.end(), bind1st(mem_fun_ref(&vector<int>::push_back), b));
}

But I get 3 errors:

1>c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(281) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(282) : error C2535: 'void std::binder1st<_Fn2>::operator ()(const int &(&)) const' : member function already defined or declared
1>        with
1>        [
1>            _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : see declaration of 'std::binder1st<_Fn2>::operator ()'
1>        with
1>        [
1>            _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1>        ]

reference to reference is illegal makes me think that the function needs to take a parameter by value. But of course, this is not possible to change in vector, and it's not possible to change it in my code either. Is there a simple change to get this to work? I need a solution that's a 1-liner.

+1  A: 

Just use bind. The mem_fun versions are too difficult.

for_each(a.begin(), a.end(),
  boost::bind(&vector<int>::push_back, boost::ref(b), _1));

Another way that doesn't require the use of ref is to pass a pointer to the vector to be modified:

for_each(a.begin(), a.end(),
  boost::bind(&vector<int>::push_back, &b, _1));
1800 INFORMATION
This doesn't seem to do anything when I tried it!
rlbond
Oh, it needs boost::ref.
rlbond
something like that?
1800 INFORMATION
A: 

I know that you've said you don't want to use back_inserter, probably because you've given just simplified example code.

For anyone else wondering how to do exactly what you're trying to do, and happy to use it, use back_inserter:

std::copy(a.begin(), a.end(), std::back_inserter(b));
Roger Lipscombe
Actually, a better way is b.insert(b.end(), a.begin(), a.end());
rlbond
A: 

That said, there's always other_mem_fun, which I cooked up before I knew about boost. This might fit.

Roger Lipscombe
Any reason for not making this an edit of your previous answer?
anon
Because it's actually an answer to the question, whereas my other answer was more of an aside.
Roger Lipscombe
A: 

This problem was explained in "Exceptional C++ Style" by Herb Sutter, page 28-30. One probably cannot safely create a pointer to a vector<int>::push_back method as one needs to be sure of exact signature of the member function, which may not be obvious even for vector<int>::push_back in Standard Library. This is because (in Standard Library):

  1. A member function signature with default parameters might be replaced by "two or more member function signatures with equivalent behavior.
  2. A member function signature might have additional defaulted parameters.

In the end, Herb Sutter advised that

  1. Use mem_fun, Just Not with the Standard Library
  2. Use Pointers to Member Functions, Just Not with the Standard Library
rayhan