Reputation: 5677
I've recently started using Boost.Asio in a project and would like to know whether anyone knows a clean solution to transfer ownership of a newly created socket to tcp::acceptor::async_accept, which would in turn transfer this ownership to the accept handler function.
This isn't an incoherent desire, mind you, since the handler is to be called exactly once.
I have noticed I can't std::bind() an std::unique_ptr<> as parameter, since std::bind() requires its parameters to be CopyConstructible, and rightfully so. Not only that, but Boost's AcceptHandler concept is also required to be CopyConstructible.
So my options would be:
or
I'm pretty much at a loss here. Can anyone enlighten me?
Upvotes: 4
Views: 1331
Reputation: 8855
I tried to find a way to do this using the c++0x standard library, but could not. Eventually I settled on writing my own rvalue_reference_wrapper and rvalue_ref() convenience class. As per usual with std::bind, you need to wrap your non copyable object in something that is copyable (reference_wrapper is the best example). You could also have just passed a pointer, but that means changing your interface.
This worked on my machine:
#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();
}
I have not made the code bulletproof, but welcome some discussion about the need for an rvalue_reference_wrapper, or how to simulate one using std::reference_wrapper.
Also, for your specific case, you will likely need to write a difference version of rvalue_reference_wrapper, which holds the object by value not by rvalue reference, since your original unique_ptr is likely going to leave scope (and be destroyed) since you are using async asio calls.
Upvotes: 1