如何直接将成员函数绑定到Visual Studio 11中的std :: function?

dan*_*jar 19 c++ member-functions c++11 std-function

我可以轻松地将成员函数绑定到a std::function带有capture子句的lambda表达式.

class Class
{
    Class()
    {
        Register([=](int n){ Function(n); });
    }

    void Register(std::function<void(int)> Callback)
    {

    }

    void Function(int Number)
    {

    }
};
Run Code Online (Sandbox Code Playgroud)

但我想直接绑定它们,如下所示.

// ...
Register(&Class::Function);
// ...
Run Code Online (Sandbox Code Playgroud)

我认为根据C++ 11标准,这应该得到支持.但是,在Visual Studio 11中,我收到了这些编译器错误.

错误C2440:'换行':无法从'int'转换为'Class*'

错误C2647:'.*':无法在'int'上取消引用'void(__thiscall Class ::*)(int)'

jua*_*nza 36

我认为根据C++ 11标准,这应该得到支持

不是真的,因为非静态成员函数具有隐式的第一个类型参数(cv-qualified)YourType*,所以在这种情况下它不匹配void(int).因此需要std::bind:

Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));
Run Code Online (Sandbox Code Playgroud)

例如

Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));
Run Code Online (Sandbox Code Playgroud)

编辑您提到要使用相同的Class实例调用它.在这种情况下,您可以使用简单的非成员函数:

void foo(int n)
{
  theClassInstance.Function(n);
}
Run Code Online (Sandbox Code Playgroud)

然后

Class c;
c.Register(foo);
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 31

根据Stephan T. Lavavej - "避免使用bind(),...,使用lambdas". https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s

在这种情况下:

Class()
{
    Register([this](int n){ Function(n); });
}
Run Code Online (Sandbox Code Playgroud)


Som*_*ude 9

你可以使用std::bind:

using namespace std::placeholders;  // For _1 in the bind call

// ...

Register(std::bind(&Class::Function, this, _1));
Run Code Online (Sandbox Code Playgroud)


pet*_*hen 8

在 C++ 17 中,您可以使用:

Register([=](auto && ...args){ return Function(args...); });
Run Code Online (Sandbox Code Playgroud)

这很不错,尤其是当参数列表较长时。当然,成员函数的参数列表必须与 的参数std::function列表兼容。

  • 并且示例代码在 C++20 中不再有效,因为 [通过 `[=]` 隐式捕获 `this` 已被弃用](https://www.open-std.org/jtc1/sc22/wg21 /docs/papers/2018/p0806r2.html)。 (2认同)