简体   繁体   English

使用boost:bind绑定一个std :: function

[英]Using boost:bind to bind a std::function

I have a problem using boost::bind with a function stored into std::function. 我在使用boost :: bind和存储在std :: function中的函数时遇到问题。

This is related to boost::asio: I am building a basic UDP server. 这与boost :: asio有关:我正在构建基本的UDP服务器。 So, first lets see some code that compiles fine without std::function (whole code on Coliru here , uncomment the define to see the problem): 因此,首先让我们看一些无需 std :: function就可以正常编译的代码(Coliru上的整个代码,请取消注释定义以查看问题):

Here only the relevant part: 这里只有相关部分:

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 );
};

As you can see, I am passing the handler _rx_handler (aka "callback") to the boost::asio function, so that when something gets received, the function will be called. 如您所见,我将处理程序_rx_handler (也称为“回调”)传递给boost :: asio函数,以便在接收到某些内容时将调用该函数。 As I need a third argument and the "asio" function requires a specific function signature, I am using boost::bind. 由于我需要第三个参数,而“ asio”函数需要特定的函数签名,因此我使用boost :: bind。 So far so good. 到现在为止还挺好。

Now , I want to inherit this class into another one, where I can define some more specific things to do upon receiving data. 现在 ,我想将这个类继承到另一个类中,在这里我可以定义一些更具体的事情来在接收数据时执行。 So I replace in base class the handler with a std::function, with same signature: 因此,我在基类中将处理程序替换为具有相同签名的std :: function:

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

or, more conveniently, using a typedef; 或者,更方便地使用typedef;

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

That way (I thought), I can add a member function to assign any member function from an inherited class: 这样(我认为),我可以添加一个成员函数以从继承的类分配任何成员函数:

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

Unfortunately, this does not compile. 不幸的是,这不能编译。 GCC 5.4.1 says: 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 /usr/include/boost/bind/bind.hpp:69:37:错误:'std :: function udp_server :: *'不是类,结构或联合类型

But when I check cppreference , I read that it is a class template... 但是当我检查cppreference时 ,我读到它一个类模板。

After looking at this page, I also tried to access the pointer on function with target() : 看完此页面后,我还尝试使用target()访问函数上的指针:

boost::bind(
    &udp_server::_rx_handler.target(),
    this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred,
    42
)

but this does not compile either: 但这也不编译:

error: no matching function for call to 'std::function::target()' udp_server::_rx_handler.target(), 错误:没有匹配的函数调用'std :: function :: target()'udp_server :: _ rx_handler.target(),

Question : What is wrong here? 问题 :这是怎么了? I thought a "real" function and std::function were interchangeable? 我以为“真正的”功能和std :: function是可以互换的? How can I make this work? 我该如何进行这项工作?

Addendum: I have the feeling that this is possibly related to my lack of knowledge on how the whole binding thing works, so thanks for any insights! 附录:我觉得这可能与我对整个绑定事物的工作原理缺乏了解有关,因此感谢您的见解!

Possibly related: std::function and std::bind: what are they & when they should be used? 可能相关: std :: function和std :: bind:它们是什么以及何时应使用?

Your binding should be modified as follow: 您的绑定应修改如下:

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
        )
    );
}

You change _rx_handler from void (udp_server::*)(const boost::system::error_code&, std::size_t bytes_rx, int); 您将_rx_handlervoid (udp_server::*)(const boost::system::error_code&, std::size_t bytes_rx, int);更改为void (udp_server::*)(const boost::system::error_code&, std::size_t bytes_rx, int); to std::function<void(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)>

So you no longer have to bind to an instance to udp_server . 因此,您不再需要绑定到udp_server的实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM