使用 boost:bind 绑定 std::function
Using boost:bind to bind a std::function
我在将 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
(也称为 "callback")传递给 boost::asio 函数,以便在接收到某些内容时调用该函数。
因为我需要第三个参数并且 "asio" 函数需要特定的函数签名,所以我使用 boost::bind。到目前为止一切顺利。
现在,我想把这个class继承到另一个,在那里我可以定义一些更具体的接收数据的事情。
所以我在基础 class 中用 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;
这样(我想),我可以添加一个成员函数来分配继承的任何成员函数 class:
void assignCallback( CALLBACK_T f )
{
_rx_handler = f;
}
不幸的是,这无法编译。
GCC 5.4.1 说:
/usr/include/boost/bind/bind.hpp:69:37: error: ‘std::function udp_server::*’ is not a class, struct, or union type
但是当我检查 cppreference 时,我读到它 是 一个 class 模板...
看完这个页面后,我也尝试访问函数指针 target()
:
boost::bind(
&udp_server::_rx_handler.target(),
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
42
)
但这也不编译:
error: no matching function for call to ‘std::function::target()’
udp_server::_rx_handler.target(),
问题:这里有什么问题?我以为 "real" 函数和 std::function 可以互换?
我怎样才能使这项工作?
附录:我觉得这可能与我对整个绑定的工作原理缺乏了解有关,所以感谢您的任何见解!
可能相关:std::function and std::bind: what are they & when they should be used?
您的绑定应修改如下:
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_handler
从 void (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
。
我在将 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
(也称为 "callback")传递给 boost::asio 函数,以便在接收到某些内容时调用该函数。
因为我需要第三个参数并且 "asio" 函数需要特定的函数签名,所以我使用 boost::bind。到目前为止一切顺利。
现在,我想把这个class继承到另一个,在那里我可以定义一些更具体的接收数据的事情。 所以我在基础 class 中用 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;
这样(我想),我可以添加一个成员函数来分配继承的任何成员函数 class:
void assignCallback( CALLBACK_T f )
{
_rx_handler = f;
}
不幸的是,这无法编译。 GCC 5.4.1 说:
/usr/include/boost/bind/bind.hpp:69:37: error: ‘std::function udp_server::*’ is not a class, struct, or union type
但是当我检查 cppreference 时,我读到它 是 一个 class 模板...
看完这个页面后,我也尝试访问函数指针 target()
:
boost::bind(
&udp_server::_rx_handler.target(),
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
42
)
但这也不编译:
error: no matching function for call to ‘std::function::target()’ udp_server::_rx_handler.target(),
问题:这里有什么问题?我以为 "real" 函数和 std::function 可以互换? 我怎样才能使这项工作?
附录:我觉得这可能与我对整个绑定的工作原理缺乏了解有关,所以感谢您的任何见解!
可能相关:std::function and std::bind: what are they & when they should be used?
您的绑定应修改如下:
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_handler
从 void (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
。