为什么要使用mem_fn?

Jon*_*an. 12 c++ stdbind c++11

我很困惑为什么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);
Run Code Online (Sandbox Code Playgroud)

我见过的所有代码示例都是:

//some defined member function
Item::Foo(int n);

DoBinding(std::mem_fn(&Item::Foo));
Run Code Online (Sandbox Code Playgroud)

为什么不能简单地:

DoBinding(&Item::Foo);
Run Code Online (Sandbox Code Playgroud)

似乎后者可以调用而不必使用std :: mem_fn,那么为什么需要呢?

Bar*_*rry 19

这是因为通用代码期望UnaryFunctionBinaryFunction将使用常规调用语法直接调用它.因此,要选择任意算法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;
}
Run Code Online (Sandbox Code Playgroud)

如果你打电话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::threadstd::function...),因为它们都有明确处理指向成员的指针.而且由于DoBinding()自己打电话std::bind(),std::mem_fn 在这种情况下没有理由.


这里被提议摆脱这个语法差别:p0312中.它进展不顺利.


Nic*_*las 12

这通常是因为写入的人DoBinding(std::mem_fn(&Item::Foo))不知道DoBinding可以直接获取成员指针.

记住:std::sort(..., &Item::Foo)失败,因为sort期望值是可直接调用的函数对象.成员指针不是.实际上,当给定成员指针而不是直接可调用类型时,C++标准库中的每个算法都会失败.你DoBinding唯一的工作,因为你正在使用std::bind,它有成员指针的特殊重载.打电话的DoBinding人不一定知道你在做那件事.

大多数通过模板参数获取callable的代码都会阻塞成员指针.所以为了安全起见,我们不会将成员指针作为可以直接调用的对象传递; 用mem_fn它把它变成这样一个对象.