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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17131768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:57:14  来源:igfitidea点击:

How to directly bind a member function to an std::function in Visual Studio 11?

c++c++11member-functionsstd-function

提问by danijar

I can easily bind member functions to a std::functionby wrapping them with a lambda expression with capture clause.

我可以很容易地将成员函数绑定到 a std::function,方法是用带有捕获子句的 lambda 表达式包装它们。

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

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

    }

    void Function(int Number)
    {

    }
};

But I want to bind them directly, something like the following.

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

// ...
Register(&Class::Function);
// ...

I think according to the C++11 standard, this should be supported. However, in Visual Studio 11 I get these compiler errors.

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

error C2440: 'newline' : cannot convert from 'int' to 'Class *'

error C2647: '.*' : cannot dereference a 'void (__thiscall Class::* )(int)' on a 'int'

错误 C2440:“换行符”:无法从“int”转换为“Class *”

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

回答by juanchopanza

I think according to the C++11 standard, this should be supported

我觉得按照C++11标准,这个应该是支持的

Not really, because a non-static member function has an implicit first parameter of type (cv-qualified) YourType*, so in this case it does not match void(int). Hence the need for std::bind:

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

Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));

For example

例如

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

EditYou mention that this is to be called with the same Classinstance. In that case, you can use a simple non-member function:

编辑你提到这是用同一个Class实例调用的。在这种情况下,您可以使用一个简单的非成员函数:

void foo(int n)
{
  theClassInstance.Function(n);
}

then

然后

Class c;
c.Register(foo);

回答by Andy

According to Stephan T. Lavavej - "Avoid using bind(), ..., use lambdas". https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s

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

In this case:

在这种情况下:

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

回答by Some programmer dude

You can use std::bind:

您可以使用std::bind

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

// ...

Register(std::bind(&Class::Function, this, _1));

回答by peterchen

In C++ 17, you can use:

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

Register([=](auto && ...args){ return Function(args...); });

which is sweet especially if the argument list is longer long. Of course the member function's argument list must then be compatible with the std::function's ones.

这是甜蜜的,尤其是如果参数列表更长。当然,成员函数的参数列表必须与 的参数列表兼容std::function

回答by Richard

With std::functionand std::bind, you can treat different class member function the same.

使用std::functionand std::bind,您可以将不同的类成员函数视为相同。

#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;

class Foo
{
public:
    void foo(const string &msg)
    {
        cout << msg << '\n';
    }
};

class Bar
{
public:
    void bar(const string &msg, const string &suffix)
    {
        cout << msg << suffix << '\n';
    }
};

int main(int argc, char **argv)
{
    Foo foo;
    Bar bar;

    vector<function<void (const string &msg)>> collection;
    collection.push_back(bind(&Foo::foo, &foo, _1));
    collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));

    for (auto f : collection) {
        f("foo");
    }

    return 0;
}