Given a type which is non-copyable but movable, I am trying to construct a boost::ptr_vector
of this type and return it from a function. I am using Visual Studio 2013.
struct NonCopyableButMovable
{
using this_type = NonCopyableButMovable;
this_type() {}
this_type(this_type const &) = delete;
this_type & operator =(this_type const &) = delete;
this_type(this_type &&) {} // no default move ctr in VS2013
this_type & operator =(this_type &&) {} // no default move assignment in VS2013
};
boost::ptr_vector<NonCopyableButMovable> make_ptr_vector()
{
boost::ptr_vector<NonCopyableButMovable> res;
//return res; // (1)
//return std::move(res); // (2)
return boost::ptr_vector<NonCopyableButMovable>(); // (3)
}
I can only get (3) to compile: the temporary ptr_vector
gets moved. With (1) and (2), the compiler calls boost::new_clone
which attempts to call NonCopyableButMovable
's copy constructor.
According to this FAQ answer, section "Moving out of functions", (1) should work, i.e. res
should be moved, not copied.
According to this thread, (2) can be used as a workaround for compilers that are not fully standard-conformant, but for a reason I don't understand, boost::new_clone
also gets called with (2).
Note that if I replace boost::ptr_vector
with std::vector
, the three ways of returning compile fine.
Is there something broken in Boost ptr_containers' move semantics with VS2013? What happens in case (2)? What would be a workaround to implement such a ptr_container factory function?