我最近开始在一个项目中使用 Boost.Asio,想知道是否有人知道将新创建的套接字的所有权转移到 tcp::acceptor::async_accept 的干净解决方案,这将反过来转移这个所有权接受处理函数。
请注意,这并不是一个不连贯的愿望,因为处理程序只被调用一次。
我注意到我不能将 std::bind() 和 std::unique_ptr<> 作为参数,因为 std::bind() 要求其参数是 CopyConstructible,这是理所当然的。不仅如此,Boost 的 AcceptHandler 概念也要求是 CopyConstructible。
所以我的选择是:
- 采用已弃用的 std::auto_ptr<> 方法使用复制构造函数移动对象,这可能会在新版本的 Boost.Asio 上引起隐蔽的错误。
- 使用 std::shared_ptr<> 并且一旦不再需要指针,即当它到达实际的处理程序函数时,就无法从指针上取下共享所有权(这是在 http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/examples.html 处的示例中完成工作的方式据我所知)。
或
- 你有更好的主意。
我在这里几乎不知所措。谁能赐教一下?
最佳答案
我试图找到一种使用 c++0x 标准库来完成此操作的方法,但没有成功。 最终我决定编写自己的 rvalue_reference_wrapper 和 rvalue_ref() 便利类。按照 std::bind 的惯例,您需要将不可复制的对象包装在可复制的对象中(reference_wrapper 是最好的例子)。您也可以只传递一个指针,但这意味着更改您的界面。
这在我的机器上有效:
#include <iostream>
#include <functional>
#include <memory>
template< class T >
struct rvalue_reference_wrapper
{
rvalue_reference_wrapper( T&& t )
: t_(std::move(t))
{}
operator T&&() const volatile
{
return std::move(t_);
}
private:
T&& t_;
};
template< class T >
rvalue_reference_wrapper<T> rvalue_ref( T&& t )
{
return rvalue_reference_wrapper<T>(std::move(t));
}
void go( std::unique_ptr<int> i )
{
std::cout << *i << std::endl;
}
int main()
{
std::unique_ptr<int> i(new int(1));
auto b = std::bind( go, rvalue_ref(std::move(i)) );
//auto b = std::bind( go, std::ref(std::move(i)) ); // Wont work
b();
}
我没有使代码防弹,但欢迎讨论是否需要 rvalue_reference_wrapper,或者如何使用 std::reference_wrapper 来模拟。
此外,对于您的特定情况,您可能需要编写一个不同版本的 rvalue_reference_wrapper,它按值而不是按右值引用保存对象,因为您的原始 unique_ptr 可能会离开范围(并被销毁),因为您正在使用异步 asio 调用。
关于c++ - 使用 tcp::acceptor::async_accept 的套接字指针所有权转移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3086782/