I wanted to pass a mem_fn argument to bind but the compiler doesn't seem to allow it.
For example this works fine:
accumulate(cbegin(foos), cend(foos), 0, bind(plus<int>(), placeholders::_1, bind(&foo::r, placeholders::_2)));
But when I try to use the mem_fn functor I get about a page of errors:
accumulate(cbegin(foos), cend(foos), 0, bind(plus<int>(), placeholders::_1, mem_fn(&foo::r)));
/usr/include/c++/6/bits/stl_numeric.h: In instantiation of ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = __gnu_cxx::__normal_iterator >; _Tp = int; _BinaryOperation = std::_Bind(std::_Placeholder<1>, std::_Mem_fn)>]’:
prog.cpp:20:102: required from here
/usr/include/c++/6/bits/stl_numeric.h:154:22: error: no match for call to ‘(std::_Bind(std::_Placeholder<1>, std::_Mem_fn)>) (int&, foo* const&)’
To understand this, think about what it would mean if you just passed a literal to
bind's 3rd argument. For Example if you had done:The result would have been
size(foos) * 13, becausepluswould have used13as it's addend on each iteration.Won't compile because it's attempting to pass the result of
mem_fn(&foo::r)as the addend toplus. Since that can't be converted to anintpluscan't accept that. But even if it could be converted to anint, that's not what you're looking for, you want to take the 2nd argument and callfoo::ron it, passing the result toplus. Thus we know we need to see,placeholders::_2used somewhere in the statement, conveying the 2nd argument for the calling of it'srmethod.We need to bind
placeholders::_2to be bound to a functor which will call thermethod on it's parameter. The binding will of course requirebind, but actuallybindcan take a method as it's 1st argument.That said, the
bind(&foo::r, placeholders::_2)statement from your working code doesn't make any sense in non-nested form; that functor doesn't even take 2 parameters! c++ actually has special rules for handling abindnested within anotherbind, so that they can share the outerbind's placeholders, lest there be no way to convey a bound argument to a nested expression:The only way to use
mem_fnin this expression would be to pass it it's result tobindfor the conveying ofplaceholders::_2:bind(mem_fn(&foo::r), placeholders::_2)This works, but is an unnecessary step when the simplebind(&foo::r, placeholders::_2)will suffice. Thus the best way to generate this functor is either with your proffered statement:Or by using a lambda: