使用boost:bind绑定std :: function

时间:2018-01-24 10:17:54

标签: c++ function boost boost-bind

我使用boost :: bind与存储在std :: function中的函数有问题。

这与boost :: asio有关:我正在构建一个基本的UDP服务器。 所以,首先让我们看一些代码编译好没有 std :: function(整个代码on Coliru here,取消注释定义以查看问题):

这里只有相关部分:

class udp_server
{
        void start_receive()
        {
            _socket.async_receive_from(
                boost::asio::buffer( _buffer ),
                _remote_endpoint,
                boost::bind(
                    &udp_server::_rx_handler,
                    this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred,
                    42
                )
            );
        }

        void _rx_handler( const boost::system::error_code&, std::size_t bytes_rx, int );
};

正如您所看到的,我将处理程序_rx_handler(又称“回调”)传递给boost :: asio函数,以便在收到某些内容时,将调用该函数。 因为我需要第三个参数而“asio”函数需要特定的函数签名,所以我使用的是boost :: bind。到目前为止一切都很好。

现在,我想将这个类继承到另一个类,在那里我可以定义一些接收数据时要做的更具体的事情。 所以我在基类中用std :: function替换处理程序,具有相同的签名:

std::function< void( const boost::system::error_code&, std::size_t bytes_rx, int )> _rx_handler;

或更方便地使用typedef;

typedef std::function< void( const boost::system::error_code&, std::size_t bytes_rx, int ) > CALLBACK_T;
...
CALLBACK_T _rx_handler;

那样(我想),我可以添加一个成员函数来从继承的类中分配任何成员函数:

void assignCallback( CALLBACK_T f )
{
    _rx_handler = f;
}

不幸的是,这不会编译。 GCC 5.4.1说:

  

/usr/include/boost/bind/bind.hpp:69:37:错误:'std :: function udp_server :: *'不是类,结构或联合类型

但是当我检查cppreference时,我读到 是一个类模板......

查看此页面后,我还尝试使用target()

访问函数指针
boost::bind(
    &udp_server::_rx_handler.target(),
    this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred,
    42
)

但是这不会编译:

  

错误:没有匹配函数来调用'std :: function :: target()'         udp_server :: _ rx_handler.target(),

问题:这里有什么问题?我认为一个“真正的”函数和std :: function是可以互换的吗? 我怎样才能做到这一点?

附录:我觉得这可能与我对整个装订工作原理缺乏了解有关,所以感谢任何见解!

可能相关:std::function and std::bind: what are they & when they should be used?

1 个答案:

答案 0 :(得分:2)

您的绑定应修改如下:

void start_receive()
{
    _socket.async_receive_from(
        boost::asio::buffer( _buffer ),
        _remote_endpoint,
        boost::bind(
            udp_server::_rx_handler,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred,
            42
        )
    );
}

您将_rx_handlervoid (udp_server::*)(const boost::system::error_code&, std::size_t bytes_rx, int);更改为std::function<void(const boost::system::error_code&, std::size_t bytes_rx, int)>

因此您不再需要将实例绑定到udp_server