c ++绑定成员函数(回调)

时间:2017-09-24 15:10:34

标签: c++ eclipse

我试图将成员函数绑定到随后注册的函数指针。有一个我无法解决的错误:

<functional> and all gcc stdXX (stdio.h, stdlib.h,...)

回调类型在atl :: hal :: lib :: uart

中注册
void (*f_callback_t)(void* /*data*/, callback_t /*type*/);

atl :: hal :: obj :: uart

中的对象
class CLI
{
public:

void init() 
{
    atl::hal::lib::uart::f_callback_t pevt;

    // ERROR !!! <----------------------------------------------
    pevt = std::bind(
        &atl::hal::obj::uart::obj::_eventhandler,
        this,
        std::placeholders::_1,
        std::placeholders::_2);
}

private:
  void _eventhandler(
      void* data,
      atl::hal::lib::uart::callback_t type)
  {
    M_ASSERT_BOOL(false);
  }
}

错误

cannot convert 'std::_Bind_helper<false, void (atl::hal::obj::uart::obj::*)(void*, atl::hal::lib::uart::callback_t), atl::hal::obj::uart::obj*, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (atl::hal::obj::uart::obj::*)(void*, atl::hal::lib::uart::callback_t)>(atl::hal::obj::uart::obj*, std::_Placeholder<1>, std::_Placeholder<2>)>}' to 'atl::hal::lib::uart::f_callback_t {aka void (*)(void*, atl::hal::lib::uart::callback_t)}' in assignment

1 个答案:

答案 0 :(得分:0)

您无法将绑定结果存储在简单的函数指针类型中。

您可以使用以下类型特征检查定义的类型是否为bind_expression(即,它存储某种类型的绑定):

std::is_bind_expression<bind_type>::value

简短解决方案:

只需使用auto关键字,让编译器为您推导出绑定表达式类型。

长期解决方案

手动定义正确的类型。

对于简化方案(因为您没有显示atl::hal::obj::uart::obj代码),要将绑定存储到CLI::_eventhandler,最终代码将如下所示:

class CLI
{
public:
    using bind_type = decltype(std::bind(std::declval<void (CLI::*)()>(), std::declval<CLI*>(), std::declval<const std::_Ph<1>&>(), std::declval<const std::_Ph<2>&>()));

void init()
    {   
        bind_type  pevt1 = std::bind(
            &CLI::_eventhandler,
            this,
            std::placeholders::_1,
            std::placeholders::_2);
    }

private:
    void _eventhandler()
    { }
};

<强>详细信息:

decltype(std::bind(std::declval<void (CLI::*)()>(), std::declval<CLI*>(), std::declval<const std::_Ph<1>&>(), std::declval<const std::_Ph<2>&>()));
  • decltype(...):返回括号内表达式的类型声明。
  • std::bind:我们想要结果类型的std :: bind所以我们必须在这里包含调用。
  • std::declval<void (CLI::*)()>()
    • std::declval<T>():只需返回对类型T的引用,这样我们就不需要在decltype中使用虚拟对象或表达式。
    • std::declval<void (CLI::*)()>():返回对declval生成的CLI成员函数指针的引用,因此decltype可以推断出它的类型。
  • std::declval<CLI*>():与上面相同,但返回指向CLI *(*this指针参数)的指针。
  • std::declval<const std::_Ph<2>&>():占位符类型,我无法详细说明,因为我从错误消息中提取了它的名称。可能有一个更好,更安全的方式来定义这个,也许更聪明的人可以帮助:)。
  • std::declval<const std::_Ph<2>&>():第二个占位符。