I'm confused as to why std::mem_fn
is needed.
I have a function that takes in any callable (lambda, function pointer, etc),and binds it to an argument.
Eg:
template<class T>
void Class::DoBinding(T callable) {
m_callable = std::bind(callable, _1, 4);
}
//somewhere else
Item item;
m_callable(item);
All code samples I've seen do:
//some defined member function
Item::Foo(int n);
DoBinding(std::mem_fn(&Item::Foo));
Why can't it simply be:
DoBinding(&Item::Foo);
It seems the latter is callable without having to use std::mem_fn, so why is it needed?
This is because generic code that expects UnaryFunction
or BinaryFunction
will invoke it directly with the regular call syntax. So to pick an arbitrary algorithm like for_each
, it could well be implemented like:
template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
for (; first != last; ++first) {
f(*first); // <== N.B. f(*first)
}
return f;
}
If you called for_each()
with &Item::Foo
, the code try to call (&Item::Foo)(x)
, which is ill-formed since for pointers to members you have to write (x.*&Item::Foo)()
. It's that syntactical difference that mem_fn
is meant to solve: mem_fn
deals with the invocation syntax of pointers to members so that you can use all the algorithms with pointers to members as well as functions and function objects. You cannot have for_each(v.begin(), v.end(), &Item::Foo)
but you can have for_each(v.begin(), v.end(), mem_fn(&Item::Foo))
.
This works just fine in std::bind()
(and std::thread
and std::function
and ...) natively since those all have explicit handling for pointers to members separately. And since DoBinding()
itself calls std::bind()
, there is no reason for std::mem_fn
in this case.
There is was a proposal to get rid of this syntactic difference: P0312. It did not go well.