If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptr
s into the vector.
#include <vector> #include <memory> int main() { using move_only = std::unique_ptr<int>; std::vector<move_only> v { move_only(), move_only(), move_only() }; }
Obviously that cannot work because std::unique_ptr
is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
No. It doesn't call the move constructor. To call move constructor of element you will have to call std::move while pushing to vector itself.
Begin Declare v of vector type. Call push_back() function to insert values into vector v. Print “Vector elements:”. for (int a : v) print all the elements of variable a.
Unlike static containers like an array, a vector does not need a size to be initialized with.
How to Initialize a Vector Using a Constructor in C++ We can also initialize vectors in constructors. We can make the values to be a bit dynamic. This way, we don't have to hardcode the vector's items.
Edit: Since @Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator> #include <vector> #include <memory> int main(){ using move_only = std::unique_ptr<int>; move_only init[] = { move_only(), move_only(), move_only() }; std::vector<move_only> 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 <utility> #include <type_traits> template<class T> 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<class T> typename std::enable_if< !std::is_lvalue_reference<T>::value, rref_wrapper<T> >::type rref(T&& v){ return rref_wrapper<T>(std::move(v)); } // lvalue reference can go away template<class T> void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> 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<class U> initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>>
created by the brace-init-list ({...}
) won't convert to the initializer_list<move_only>
that the vector<move_only>
takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()), rref(move_only()), rref(move_only()) }; std::vector<move_only> v(il.begin(), il.end());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With