C++ std::具有异步操作的函数回调

C++ std::具有异步操作的函数回调,c++,c++11,asynchronous,callback,std-function,C++,C++11,Asynchronous,Callback,Std Function,我想在包装类中使用std::函数作为回调参数。 该类包装了一个允许异步TCP/IP操作的库(实际上是boost::asio,但boost::asio和TCP/IP在这里都不重要,只是它有异步操作) 库函数允许我传递另一个回调函数对象,该对象在请求的操作完成时被异步调用。 根据异步操作的结果,我希望调用客户端指定的回调或启动进一步的操作。 下面的代码试图勾勒出我的意图 using ConnectHandler = std::function<void(boost::system::error

我想在包装类中使用std::函数作为回调参数。 该类包装了一个允许异步TCP/IP操作的库(实际上是boost::asio,但boost::asio和TCP/IP在这里都不重要,只是它有异步操作)

库函数允许我传递另一个回调函数对象,该对象在请求的操作完成时被异步调用。 根据异步操作的结果,我希望调用客户端指定的回调或启动进一步的操作。 下面的代码试图勾勒出我的意图

using ConnectHandler = std::function<void(boost::system::error_code ec)>;

class MyConnection
{

public:

    void Connect(ConnectHandler handler);  // (1)
}

void MyConnection::Connect(ConnectHandler handler)
{
    SomeLibrary::async_connect(...,
        [handler](boost::system::error_code ec, ...) // (2)
        {
            //Depending on ec start a nested read/write operation.
            //One way or another it finally invokes the callback
            handler(ec); // (3)
        });
}
我的问题是: 在(1)中,f.e.声明连接方法的最佳方式是什么

根据这一点,如何在(2)中的lambda capture子句中正确捕获回调处理程序,以便在(3)中调用它

旁注:
在所有异步操作完成之前,MyConnection的客户端实例永远不会超出范围

std::function
移动成本较低,因此可以接受按值移动。按
&&
移动几乎毫无意义,充其量只能保存
移动。它强制调用者移动,而不是复制,也许调用者想要复制

复制不便宜,因此可以考虑在可调用对象中使用<代码>移动< /代码>捕获。

在C++14中,这非常简单:

[handler=std::move(handler)]
作为捕获列表(通用捕获表达式)

在C++11中,您需要编写一个自定义对象来执行此操作

struct custom_work {
  ConnectHandler handler;
  void operator()(boost::system::error_code ec, ...) const {
    //Depending on ec start a nested read/write operation.
    //One way or another it finally invokes the callback
    handler(ec); // (3)
  }
};
然后


它的缺点是将代码从内联移动到外联。

您是否考虑过使用boost.signals2,或查看其注册回调的接口?请注意,C++11 lambdas不能“通过移动捕获”(这已在C++14中引入)。根据
async\u connect
,您可以通过使用支持将处理程序移动到函数对象中的手写函数对象类型来实现更好的性能。
[connectHandler]
--我假设应该是
[handler]
?我还没有考虑boost.signals2,但会这样做。关于C++14:这很有趣,实际上我欢迎C++14使用lambda init captures,但目前我与VS2013社区版绑定,它似乎不支持init captures。@Yakk谢谢,已编辑。
[handler=std::move(handler)]
struct custom_work {
  ConnectHandler handler;
  void operator()(boost::system::error_code ec, ...) const {
    //Depending on ec start a nested read/write operation.
    //One way or another it finally invokes the callback
    handler(ec); // (3)
  }
};
SomeLibrary::async_connect(...,
    some_work{std::move(handler)}
);