I want to move a range of objects into uninitialized memory (using move-construction). Since there is no move-counterpart to std::uninitialized_copy
, I came up with two options: either use std::move
with raw_storage_iterator
, or resort to the manual loop:
T* dest = get_memory();
// option one
std::move(first, last, std::raw_storage_iterator<T*, T>(dest));
// option two
for (auto i=first; i != last; ++i, ++dest)
{
new(dest) T(std::move(*i));
}
Will the first option do the move-construction (thus being equivalent to the second), or copy construction, or default construction followed by move assignment? Are there other considerations to prefer one option or another?
std::raw_storage_iterator
uses a placement-new operator on assignment which in c++11 defined in terms of a copy-assignment operator taking a const lvalue reference:
§ 20.7.10 [storage.iterator]/p1:
raw_storage_iterator& operator=(const T& element);
which always calls a copy constructor (even when invoked with an rvalue).
This case has been reported as LWG issue 2127 which adds support for move-constructible types by introducing another assignment operator taking an rvalue reference, meaning it will be possible to move-construct elements to an uninitialized memory once the proposed change is adopted. Until that update takes place, you need to rely on your own for-loop. Alternatively, you could leverage the std::uninitialized_copy
algorithm defined as follows:
§ 20.7.12.2 [uninitialized.copy]/p1:
for (; first != last; ++result, ++first)
::new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
Once you wrap your input iterators using the std::make_move_iterator
helper function, you'll get the same effect as your hand-written for-loop:
std::uninitialized_copy(std::make_move_iterator(first)
, std::make_move_iterator(last)
, dest);
c++17 extends the set of algorithms by introducing std::uninitialized_move
:
std::uninitialized_move(first, last, dst);
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