Using Bind1St for a Method That Takes Argument by Reference

Using bind1st for a method that takes argument by reference

std::bind1st and std::bind2nd don't accept functors which take reference arguments, because they themselves form references to these arguments. You can

  1. use pointers for your function inputs instead of references
  2. use boost::bind
  3. accept the performance cost of copying the string

Cannot use std::ptr_fun with function that takes reference

You cannot do this. It is a fundamental limitation to std::bind1st and std::bind2nd. The problem is that it defines two () operators, and one of them already has const & on it. So the compiler sees two identical functions. It won't be fixed since C++11 has already deprecated these methods.

See also:

Using bind1st for a method that takes argument by reference

weird compiler error using bind2nd(): "member function already defined or declared" instead of "reference to reference"

Bind2nd issue with user-defined class

referencing a member function with bind1st and mem_fun

What are you trying to accomplish with bind1st?

The bind1st function takes a binary function and adapts it to a unary function by making the first argument implicit (this may not be the best description, sorry). The return value of mem_fun is a unary function.

The mem_fun function returns an adaptor for a member function. The adapted function doesn't take any arguments, though the adaptor returned takes one argument, a pointer to the MyClass object to be used.

So, basically, your mem_fun call is returning a adaptor that takes one argument, but bind1st is expecting an adaptor that takes two arguments. There is a mem_fun1 which returns an adaptor that takes two arguments, the first being the object pointer and the second being an argument for the function, but that isn't what you want here.

In fact, I don't quite understand what you're trying to do; why is the plain mem_fun version not suitable? If you need the object pointer to be 'attached' to the adaptor, I don't think you can do that with the current standard library, unless you use bind.

Of course, you could make a wrapper class that holds the object pointer, and then just define operator() to call the adaptor with that object.

// Quick and dirty example of this.
// You could extend this with a second template parameter for return type, if
// needed. Just be sure to specialize for void if you do that.
template<typename Object>
struct bound_mem_fun_t {
bound_mem_fun_t(mem_fun_t<void, Object> f, Object* o) : fun(f), obj(o) { }
void operator()() { fun(obj); }
mem_fun_t<void, Object> fun;
Object* obj;
};

MyClass a;
bound_mem_fun_t<MyClass> func(mem_fun(&MyClass::Bar), &a);
func();

How to use bind1st and bind2nd?

The argument to bind2nd must be an AdaptableBinaryFunction. A plain binary function does not fulfill this requirement (an adaptable function required typedefs for its return and argument types, a plain function type does not provide any typedefs). You could use std::bind which is probably the better choice anyway.

Using std::bind2nd with references

You can't do that easily, sorry. Just consider it one of those cases not covered by std::bind1st and std::bind2nd (kinda like 3-argument functions etc). Boost would help - boost::bind supports references transparently, and there's also boost::ref.

If your implementation supports TR1 - latest g++ versions and VC++2008 SP1 both do - then you can use std::tr1::bind, which is for the most part same as boost::bind, but standardized.

std::function and std::bind: what are they, and when should they be used?

std::bind is for partial function application.

That is, suppose you have a function object f which takes 3 arguments:

f(a,b,c);

You want a new function object which only takes two arguments, defined as:

g(a,b) := f(a, 4, b);

g is a "partial application" of the function f: the middle argument has already been specified, and there are two left to go.

You can use std::bind to get g:

auto g = bind(f, _1, 4, _2);

This is more concise than actually writing a functor class to do it.

There are further examples in the article you link to. You generally use it when you need to pass a functor to some algorithm. You have a function or functor that almost does the job you want, but is more configurable (i.e. has more parameters) than the algorithm uses. So you bind arguments to some of the parameters, and leave the rest for the algorithm to fill in:

// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));

Here, pow takes two parameters and can raise to any power, but all we care about is raising to the power of 7.

As an occasional use that isn't partial function application, bind can also re-order the arguments to a function:

auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);

I don't recommend using it just because you don't like the API, but it has potential practical uses for example because:

not2(bind(less<T>, _2, _1));

is a less-than-or-equal function (assuming a total order, blah blah). This example normally isn't necessary since there already is a std::less_equal (it uses the <= operator rather than <, so if they aren't consistent then you might need this, and you might also need to visit the author of the class with a cluestick). It's the sort of transformation that comes up if you're using a functional style of programming, though.

Passing a member function to for_each in C++03 (no boost, no c++11)

Yes it can, using a combination of the mem_fun and bind1st templates:

void process(const vector<Wheel>& wheel) {
for_each(wheel.begin(), wheel.end(), bind1st(mem_fun(&Car::put), this));
}

The call to mem_fun creates a new function object that takes in two arguments - a Car* to act as the receiver and a Wheel, then calls put with the first parameter as the receiver and the second parameter as the argument. Calling bind1st then locks the receiver object as first parameter of this function in place.

However, I think you will need to make one small change to this code to get it to work. The bind1st adapter doesn't play well with functions that take their arguments by const reference, so you might need to change put so that it takes a Wheel by value rather than by reference.

Using std::vectorT*::push_back with std::mem_fun and std::bind1st

The problem is that binder1st defines operator() as:

operator() (const typename Operation::second_argument_type& x) const

and mem_fun1_t defines operator() as:

S operator() (T* p, A x) const

The problem is that push_back is defined as:

void vector<T>::push_back(const T &x)

So what we end up with is this:

void mem_fun1_t::operator()(vector<T *> *p, const T *&x)

And:

void binder1st::operator()(const T *&&x)

In other words, a reference to a reference to a pointer. A reference to a reference doesn't exist in C++. The only decent way I can think of fixing this is to use boost::bind instead:

vector<T*> ret;
Execute<T>( boost::bind( mem_fun(&vector<T*>::push_back), &ret, _1) );
return ret;

Also note that you had a bug, and need to pass bind &ret instead of just ret (as mem_fun expects a pointer, mem_fun_ref would work however).



Related Topics



Leave a reply



Submit