【问题标题】:std::bind not binding to a library `typedef` ed functionstd::bind 未绑定到库 `typedef` ed 函数
【发布时间】:2020-07-28 04:03:00
【问题描述】:

我正在尝试将std::bind 与具有typedefs 函数的库一起使用。

#include <iostream>
#include <string>
#include <functional>

typedef void (*GDBusReturnFunction) (void* user_data);

class Test
{
   void reply(void* user_data)
   {
      std::cout << "Hello" << std::endl;
      return;
   }

   void test_reply()
   {
      auto reply_func = std::bind(&Test::reply, this, std::placeholders::_1);
      call(reply_func);
   }

   void call(GDBusReturnFunction func)
   {}
};

int main()
{
   Test();
}

这是我得到的编译错误

prog.cc:19:11: error: cannot convert 'std::_Bind<void (Test::*(Test*, std::_Placeholder<1>))(void*)>' to 'GDBusReturnFunction' {aka 'void (*)(void*)'}
   19 |      call(reply_func);
      |           ^~~~~~~~~~
      |           |
      |           std::_Bind<void (Test::*(Test*, std::_Placeholder<1>))(void*)>
prog.cc:22:33: note:   initializing argument 1 of 'void Test::call(GDBusReturnFunction)'
   22 |   void call(GDBusReturnFunction func)
      |             ~~~~~~~~~~~~~~~~~~~~^~~~

当我将方法切换到 static 并且不使用 std::bind 时,事情会按预期工作。


我也试过了

     call(&reply_func);

但返回相同的错误

我错过了什么?

【问题讨论】:

  • 您为什么希望它能够工作? call 需要一个函数指针,而您正在传递一个由 std::bind 创建的函数对象。它们是不相关的类型。
  • 函数指针将无处存储绑定的参数。这是一个固定大小。
  • 不是这方面的专家,所以它可能不是重复的,但必须与stackoverflow.com/questions/12662891/…密切相关
  • call 应该代表库中的函数吗?如果是这样,那么它也应该有void *user_data 作为参数。否则它不能调用func,因为它不知道传递什么参数。你到底在做什么?整个问题的症结在于,一个函数指针不足以来表示一个函数。在 C++ 中,我们使用诸如模板+函子/std::function 之类的东西。在 C 中,函数通常由函数指针加上“一些东西”表示,其中“一些东西”在 void* 后面。只要求函数指针通常是错误的。
  • call 应该代表一个库中的函数。其中确实有 void * 作为参数

标签: c++ class c++17 member-function-pointers stdbind


【解决方案1】:

std::bind 返回一个未指定类型(即未指定类型的函数对象),

template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
//^^^^^^^^^^^^

不能复制到函数指针类型。

你需要使用

不过,std::bind 可以替换为 lambda function

[this](auto user_data) { this->reply(user_data); }

使用模板化 Test::call 函数的示例解决方案可能如下所示。 See a demo

#include <iostream>
#include <string>

class Test
{
public:
   // optionally you could make it also template function!
   // e.g.
   // template<typename Type>
   // void reply(Type* user_data)
   void reply(void* user_data)
   {
      std::cout << "Hello" << std::endl;
   }

   void test_reply()
   {
      call([this](auto user_data) { this->reply(user_data); });
   }

   template<typename Callable>
   void call(Callable func) const
   {
      int userData = 1; // some user data
      func(&userData);
   }
};

【讨论】:

  • GDBusReturnFunction 来自图书馆。我不认为 OP 可以只使用不同的类型。
  • GDBusReturnFunction 和 call 都来自图书馆,所以我无法更改它们.. 我将尝试std::function 方法。我想我明白为什么 std::bind 与 std::function 不同
猜你喜欢
  • 2015-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-01-26
相关资源
最近更新 更多