我很困惑为什么需要std::mem_fn
。
我有一个函数可以接受任何可调用的(lambda,函数指针等),并将它绑定到一个参数。
例如:
template<class T>
void Class::DoBinding(T callable) {
m_callable = std::bind(callable, _1, 4);
}
//somewhere else
Item item;
m_callable(item);
我见过的所有代码示例都是:
//some defined member function
Item::Foo(int n);
DoBinding(std::mem_fn(&Item::Foo));
为什么不能简单地说:
DoBinding(&Item::Foo);
看来后者可以调用而不必使用std :: mem_fn,那为什么需要呢?
答案 0 :(得分:14)
这是因为期望UnaryFunction
或BinaryFunction
的通用代码将使用常规调用语法直接调用它。因此,要选择像for_each
这样的任意算法,它可以像:
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;
}
如果您使用for_each()
致电&Item::Foo
,则代码会尝试调用(&Item::Foo)(x)
,因为指向您必须编写(x.*&Item::Foo)()
的成员的指针格式不正确。它是mem_fn
要解决的语法差异:mem_fn
处理指向成员的指针的调用语法,以便您可以使用指向成员以及函数的所有算法。功能对象。您不能拥有for_each(v.begin(), v.end(), &Item::Foo)
,但可以拥有for_each(v.begin(), v.end(), mem_fn(&Item::Foo))
。
这在std::bind()
(以及std::thread
和std::function
和...)中本身就可以正常工作,因为这些都是对指向成员的指针的明确处理。由于DoBinding()
本身会调用std::bind()
,因此在这种情况下{/ 1}} 没有理由。
是一个摆脱这种语法差异的提议:P0312。它进展不顺利。
答案 1 :(得分:10)
通常这样做是因为撰写DoBinding(std::mem_fn(&Item::Foo))
的人不知道DoBinding
可以直接获取成员指针。
请记住:std::sort(..., &Item::Foo)
将失败,因为sort
期望该值是可直接调用的函数对象。成员指针不是。实际上,当给定成员指针而不是直接可调用类型时,C ++标准库中的每个算法都会失败。您的DoBinding
仅适用,因为您正在使用std::bind
,它对成员指针有特殊的重载。 DoBinding
的来电者并不一定知道你这样做。
大多数按模板参数获取callables的代码都会阻塞成员指针。所以为了安全起见,我们不会将成员指针作为可直接调用的对象传递;使用mem_fn
将其变成这样的对象。