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

uqzxnwby  于 2023-06-25  发布在  其他
关注(0)|答案(6)|浏览(195)

我可以很容易地将成员函数绑定到std::function,方法是用一个lambda表达式和capture子句 Package 它们。

  1. class Class
  2. {
  3. Class()
  4. {
  5. Register([=](int n){ Function(n); });
  6. }
  7. void Register(std::function<void(int)> Callback)
  8. {
  9. }
  10. void Function(int Number)
  11. {
  12. }
  13. };

但我想直接绑定它们,类似于下面的代码。

  1. // ...
  2. Register(&Class::Function);
  3. // ...

我认为根据C++11标准,应该支持这一点。然而,在Visual Studio 11中,我会遇到这些编译器错误。
错误C2440:'newline':无法从“int”转换为“Class
错误C2647:“.
”:无法在“int”上解引用“void(__thiscall Class::*)(int)”

nvbavucw

nvbavucw1#

我认为根据C++11标准,这应该是支持的
实际上不是,因为非静态成员函数有一个隐式的第一个参数类型(cv限定)YourType*,所以在这种情况下它不匹配void(int)。因此需要std::bind

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

比如说,

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

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

  1. void foo(int n)
  2. {
  3. theClassInstance.Function(n);
  4. }

然后

  1. Class c;
  2. c.Register(foo);
展开查看全部
5cnsuln7

5cnsuln72#

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

  1. Class()
  2. {
  3. Register([this](int n){ Function(n); });
  4. }
idv4meu8

idv4meu83#

可以使用std::bind

  1. using namespace std::placeholders; // For _1 in the bind call
  2. // ...
  3. Register(std::bind(&Class::Function, this, _1));
rekjcdws

rekjcdws4#

在C++ 17中,你可以用途:

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

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

xggvc2p6

xggvc2p65#

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

  1. #include <iostream>
  2. #include <functional>
  3. #include <vector>
  4. using namespace std;
  5. using namespace std::placeholders;
  6. class Foo
  7. {
  8. public:
  9. void foo(const string &msg)
  10. {
  11. cout << msg << '\n';
  12. }
  13. };
  14. class Bar
  15. {
  16. public:
  17. void bar(const string &msg, const string &suffix)
  18. {
  19. cout << msg << suffix << '\n';
  20. }
  21. };
  22. int main(int argc, char **argv)
  23. {
  24. Foo foo;
  25. Bar bar;
  26. vector<function<void (const string &msg)>> collection;
  27. collection.push_back(bind(&Foo::foo, &foo, _1));
  28. collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));
  29. for (auto f : collection) {
  30. f("foo");
  31. }
  32. return 0;
  33. }
展开查看全部
ckx4rj1h

ckx4rj1h6#

正如其他人已经说过的,您可以使用std::bind。语法是相当丑陋的。因此,我提供这些宏:

  1. #define bindToThis( className, funcName ) \
  2. std::bind( &className::funcName, this, std::placeholders::_1 )
  3. #define bindToThat( className, funcName, objPtr ) \
  4. std::bind( &className::funcName, objPtr, std::placeholders::_1 )

下面是宏的一个示例实现,在第一次键入std::function以定义所需的签名(这也使其更容易阅读/使用)之后:

  1. typedef std::function<void(const int)> MyIntHandler;
  2. class MyClass
  3. {
  4. public:
  5. MyClass( const MyIntHandler handler );
  6. };
  7. ...
  8. SomeOtherClass::SomeOtherClass()
  9. : myObjPtr_( new MyClass(
  10. MyIntHandler( bindToThis( SomeOtherClass, handleSomeInt ) ) )
  11. {}
  12. void SomeOtherClass::handleSomeInt( const int i )
  13. {
  14. // Do something...
  15. }
展开查看全部

相关问题