If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptr
s into the vector.
#include
#include <
Edit: Since @Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include
#include
#include
int main(){
using move_only = std::unique_ptr;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator
will move the pointed-to element when being dereferenced.
Original answer: We're gonna utilize a little helper type here:
#include
#include
template
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template
typename std::enable_if<
!std::is_lvalue_reference::value,
rref_wrapper
>::type rref(T&& v){
return rref_wrapper(std::move(v));
}
// lvalue reference can go away
template
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template
initializer_list(initializer_list const& other);
The initializer_list
created by the brace-init-list ({...}
) won't convert to the initializer_list
that the vector
takes. So we need a two-step initialization here:
std::initializer_list> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector v(il.begin(), il.end());