Namespaces
Variants
Views
Actions

std::ranges::uninitialized_copy, std::ranges::uninitialized_copy_result

From cppreference.com
< cpp‎ | memory
 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)(C++20)(C++20)
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)

Elementary string conversions
(C++17)
(C++17)
Stacktrace
 
Dynamic memory management
Smart pointers
(C++11)
(C++11)
(C++11)
(until C++17)
(C++11)
Allocators
Memory resources
Uninitialized storage
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Garbage collection support
Miscellaneous
(C++20)
(C++11)
(C++11)
C Library
Low level memory management
 
Defined in header <memory>
Call signature
template <std::input_iterator I, std::sentinel_for<I> S1,

         no-throw-input-iterator O, no-throw-sentinel-for<O> S2>
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
ranges::uninitialized_copy_result<I, O>

ranges::uninitialized_copy( I ifirst, S1 ilast, O ofirst, S2 olast );
(1) (since C++20)
template <ranges::input_range IR, no-throw-forward-range OR>

requires std::constructible_from<ranges::range_value_t<OR>,
         ranges::range_reference_t<IR>>
ranges::uninitialized_copy_result<ranges::borrowed_iterator_t<IR>,
         ranges::borrowed_iterator_t<OR>>

ranges::uninitialized_copy( IR&& in_range, OR&& out_range );
(2) (since C++20)
Helper types
template<class I, class O>
using uninitialized_copy_result = ranges::in_out_result<I, O>;
(3) (since C++20)
1) Constructs N elements in the output range [ofirst, olast), which is an uninitialized memory area, using the input range [ifirst, ilast) as a source of initializing elements. N = min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast)).
Precondition: the input and output ranges do not overlap.
If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.
The function has the effect equal to:
for (; !(ifirst == ilast || ofirst == olast); ++ofirst, ++ifirst) {
    ::new (const_cast<void*>(static_cast<const volatile void*>(std::addressof(*ofirst))))
        std::remove_reference_t<std::iter_reference_t<O>>(*ifirst);
}
2) Same as (1), but uses in_range as the first range and out_range as the second range, as if using ranges::begin(in_range) as ifirst, ranges::end(in_range) as ilast, ranges::begin(out_range) as ofirst, and ranges::end(out_range) as olast.

The function-like entities described on this page are niebloids, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

ifirst, ilast - the range of elements to copy from
in_range - the range of elements to copy from
ofirst, olast - the destination range
out_range - the destination range.

[edit] Return value

An object equal to {ifirst + N, ofirst + N}.

[edit] Complexity

𝓞(N).

[edit] Notes

An implementation may improve the efficiency of ranges::uninitialized_copy if the value type of the output range is TrivialType.

[edit] Possible implementation

struct uninitialized_copy_fn {
    template <std::input_iterator I, std::sentinel_for<I> S1,
             no-throw-input-iterator O, no-throw-sentinel-for<O> S2>
    requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
    ranges::uninitialized_copy_result<I, O>
    operator()( I ifirst, S1 ilast, O ofirst, S2 olast ) const {
        O current {ofirst};
        try {
            for (; !(ifirst == ilast or current == olast); ++ifirst, ++current)
                ranges::construct_at(std::addressof(*current), *ifirst);
            return {std::move(ifirst), std::move(current)};
        } catch (...) { // rollback: destroy constructed elements
            for (; ofirst != current; ++ofirst)
                ranges::destroy_at(std::addressof(*ofirst));
            throw;
        }
    }
 
    template <ranges::input_range IR, no-throw-forward-range OR>
    requires std::constructible_from<ranges::range_value_t<OR>,
             ranges::range_reference_t<IR>>
    ranges::uninitialized_copy_result<ranges::borrowed_iterator_t<IR>,
             ranges::borrowed_iterator_t<OR>>
    operator()( IR&& in_range, OR&& out_range ) const {
        return (*this)(ranges::begin(in_range), ranges::end(in_range),
                       ranges::begin(out_range), ranges::end(out_range));
    }
};
 
inline constexpr uninitialized_copy_fn uninitialized_copy{};

[edit] Example

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
 
int main()
{
    const char* v[] { "This", "is", "an", "example", };
 
    if (const auto sz{std::size(v)};
        void* pbuf = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
    {
        try
        {
            auto first {static_cast<std::string*>(pbuf)};
            auto last {first + sz};
            std::ranges::uninitialized_copy(std::begin(v), std::end(v), first, last);
 
            std::cout << "{ ";
            for (auto it {first}; it != last; ++it)
                std::cout << std::quoted(*it) << ", ";
            std::cout << "};\n";
 
            std::ranges::destroy(first, last);
        }
        catch(...)
        {
            std::cout << "uninitialized_copy exception\n";
        }
        std::free(pbuf);
    }
}

Output:

{ "This", "is", "an", "example", };

[edit] See also

copies a number of objects to an uninitialized area of memory
(niebloid) [edit]
copies a range of objects to an uninitialized area of memory
(function template) [edit]