Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/ranges/uninitialized copy n"

From cppreference.com
< cpp‎ | memory
m (Example: ~)
m (Example: -',')
 
(8 intermediate revisions by 3 users not shown)
Line 2: Line 2:
 
{{cpp/memory/navbar}}
 
{{cpp/memory/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | memory}}
+
{{dcl header|memory}}
{{dcl h | Call signature}}
+
{{dcl h|Call signature}}
{{dcl | num=1 | since=c++20 |1=
+
{{dcl|num=1|since=c++20|1=
template <std::input_iterator I, __NoThrowForwardIterator O, __NoThrowSentinel<O> S>
+
template< std::input_iterator I, no-throw-input-iterator O, no-throw-sentinel-for<O> S >
 
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
 
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
ranges::uninitialized_copy_n_result<I, O>
+
        uninitialized_copy_n_result<I, O>
ranges::uninitialized_copy_n( I ifirst, std::iter_difference_t<I> count,
+
        uninitialized_copy_n( I ifirst, std::iter_difference_t<I> count,
                              O ofirst, S olast );
+
                              O ofirst, S olast );
 
}}
 
}}
{{dcl h | Helper types}}
+
{{dcl h|Helper types}}
{{dcl | num=2 | since=c++20 |1=
+
{{dcl|num=2|since=c++20|1=
template<class I, class O>
+
template< class I, class O >
 
using uninitialized_copy_n_result = ranges::in_out_result<I, O>;
 
using uninitialized_copy_n_result = ranges::in_out_result<I, O>;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Constructs {{math|N}} elements in the output range {{tt|[ofirst, olast)}}, which is an uninitialized memory area, by using the input range beginning at {{tt|ifirst}} as a source of initializing elements. {{c|1=N = min(count, ranges::distance(ofirst, olast))}}.
+
Let {{mathjax-or|\(\scriptsize N\)|N}} be {{c|ranges::min(count, ranges::distance(ofirst, olast))}}, constructs {{mathjax-or|\(\scriptsize N\)|N}} elements in the output range {{range|ofirst|olast}}, which is an uninitialized memory area, from the elements in the input range beginning at {{c|ifirst}}.
  
''Precondition:'' the input range {{tt|[ifirst, ifirst + count)}} does not overlap with the output range {{tt|[ofirst, olast)}}.
+
The input range {{range|ifirst|ifirst + count}} must not overlap with the output range {{range|ofirst|olast}}.
  
 
If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.
 
If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.
Line 26: Line 26:
 
The function has the effect equivalent to:
 
The function has the effect equivalent to:
 
{{source|1=
 
{{source|1=
auto ret = ranges::uninitialized_copy(std::counted_iterator(ifirst, count), std::default_sentinel,
+
auto ret = ranges::uninitialized_copy(std::counted_iterator(ifirst, count),
                                      ofirst, olast);
+
                                      std::default_sentinel, ofirst, olast);
 
return {std::move(ret.in).base(), ret.out};
 
return {std::move(ret.in).base(), ret.out};
 
}}
 
}}
Line 35: Line 35:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | ifirst | the beginning of the range of elements to copy from}}
+
{{par|ifirst|the beginning of the range of elements to copy from}}
{{par | count | the number of elements to copy}}
+
{{par|count|the number of elements to copy}}
{{par | ofirst, olast | the destination range.}}
+
{{par|ofirst, olast|iterator-sentinel pair denoting the destination range}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
An object equal to {{tt|{ifirst + N, ofirst + N}.}}
+
{{c|{ifirst + N, ofirst + N}<!---->}}
  
 
===Complexity===
 
===Complexity===
{{math|𝓞(N)}}.
+
{{mathjax-or|\(\scriptsize\mathcal{O}(N)\)|𝓞(N)}}.
 +
 
 +
===Exceptions===
 +
The exception thrown on construction of the elements in the destination range, if any.
  
<!-- ===Exceptions=== -->
 
 
===Notes===
 
===Notes===
An implementation may improve the efficiency of the {{c|ranges::uninitialized_copy_n}} by using {{c|ranges::copy_n}} if the value type of the output range is {{named req|TrivialType}}.
+
An implementation may improve the efficiency of the {{tt|ranges::uninitialized_copy_n}}, by using e.g. {{lc|ranges::copy_n}}, if the value type of the output range is {{named req|TrivialType}}.
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun | 1=
+
{{eq fun|1=
struct uninitialized_copy_n_fn {
+
struct uninitialized_copy_n_fn
     template <std::input_iterator I, __NoThrowForwardIterator O, __NoThrowSentinel<O> S>
+
{
 +
     template<std::input_iterator I, no-throw-input-iterator O, no-throw-sentinel-for<O> S>
 
     requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
 
     requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
 
     ranges::uninitialized_copy_n_result<I, O>
 
     ranges::uninitialized_copy_n_result<I, O>
     operator()( I ifirst, std::iter_difference_t<I> count, O ofirst, S olast ) const {
+
     operator()(I ifirst, std::iter_difference_t<I> count, O ofirst, S olast) const
         O current {ofirst};
+
    {
         try {
+
         O current{ofirst};
 +
         try
 +
        {
 
             for (; count > 0 && current != olast; ++ifirst, ++current, --count)
 
             for (; count > 0 && current != olast; ++ifirst, ++current, --count)
 
                 ranges::construct_at(std::addressof(*current), *ifirst);
 
                 ranges::construct_at(std::addressof(*current), *ifirst);
 
             return {std::move(ifirst), std::move(current)};
 
             return {std::move(ifirst), std::move(current)};
         } catch (...) { // rollback: destroy constructed elements
+
         }
 +
        catch (...) // rollback: destroy constructed elements
 +
        {
 
             for (; ofirst != current; ++ofirst)
 
             for (; ofirst != current; ++ofirst)
 
                 ranges::destroy_at(std::addressof(*ofirst));
 
                 ranges::destroy_at(std::addressof(*ofirst));
Line 75: Line 82:
 
===Example===
 
===Example===
 
{{example
 
{{example
| code=
+
|code=
 
#include <iomanip>
 
#include <iomanip>
 
#include <iostream>
 
#include <iostream>
Line 83: Line 90:
 
int main()
 
int main()
 
{
 
{
     const char* stars[] { "Procyon", "Spica", "Pollux", "Deneb", "Polaris", };
+
     const char* stars[]{"Procyon", "Spica", "Pollux", "Deneb", "Polaris"};
  
     constexpr int n {4};
+
     constexpr int n{4};
 
     alignas(alignof(std::string)) char out[n * sizeof(std::string)];
 
     alignas(alignof(std::string)) char out[n * sizeof(std::string)];
  
 
     try
 
     try
 
     {
 
     {
         auto first {reinterpret_cast<std::string*>(out)};
+
         auto first{reinterpret_cast<std::string*>(out)};
         auto last {first + n};
+
         auto last{first + n};
         auto ret {std::ranges::uninitialized_copy_n(std::begin(stars), n, first, last)};
+
         auto ret{std::ranges::uninitialized_copy_n(std::begin(stars), n, first, last)};
  
         std::cout << "{ ";
+
         std::cout << '{';
         for (auto it {first}; it != ret.out; ++it)
+
         for (auto it{first}; it != ret.out; ++it)
             std::cout << std::quoted(*it) << ", ";
+
             std::cout << (it == first ? "" : ", ") << std::quoted(*it);
 
         std::cout << "};\n";
 
         std::cout << "};\n";
  
 
         std::ranges::destroy(first, last);
 
         std::ranges::destroy(first, last);
 
     }
 
     }
     catch(...)
+
     catch (...)
 
     {
 
     {
 
         std::cout << "uninitialized_copy_n exception\n";
 
         std::cout << "uninitialized_copy_n exception\n";
 
     }
 
     }
 
}
 
}
| output=
+
|output=
{ "Procyon", "Spica", "Pollux", "Deneb", };
+
{"Procyon", "Spica", "Pollux", "Deneb"};
 
}}
 
}}
  
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/memory/ranges/dsc uninitialized_copy}}
+
{{dsc inc|cpp/memory/ranges/dsc uninitialized_copy}}
{{dsc inc | cpp/memory/dsc uninitialized_copy_n}}
+
{{dsc inc|cpp/memory/dsc uninitialized_copy_n}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 14:57, 11 October 2023

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
Defined in header <memory>
Call signature
template< std::input_iterator I, no-throw-input-iterator O, no-throw-sentinel-for<O> S >

requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
         uninitialized_copy_n_result<I, O>
         uninitialized_copy_n( I ifirst, std::iter_difference_t<I> count,

                               O ofirst, S olast );
(1) (since C++20)
Helper types
template< class I, class O >
using uninitialized_copy_n_result = ranges::in_out_result<I, O>;
(2) (since C++20)

Let N be ranges::min(count, ranges::distance(ofirst, olast)), constructs N elements in the output range [ofirstolast), which is an uninitialized memory area, from the elements in the input range beginning at ifirst.

The input range [ifirstifirst + count) must not overlap with the output range [ofirstolast).

If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.

The function has the effect equivalent to:

auto ret = ranges::uninitialized_copy(std::counted_iterator(ifirst, count),
                                      std::default_sentinel, ofirst, olast);
return {std::move(ret.in).base(), ret.out};

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 - the beginning of the range of elements to copy from
count - the number of elements to copy
ofirst, olast - iterator-sentinel pair denoting the destination range

[edit] Return value

{ifirst + N, ofirst + N}

[edit] Complexity

𝓞(N).

[edit] Exceptions

The exception thrown on construction of the elements in the destination range, if any.

[edit] Notes

An implementation may improve the efficiency of the ranges::uninitialized_copy_n, by using e.g. ranges::copy_n, if the value type of the output range is TrivialType.

[edit] Possible implementation

struct uninitialized_copy_n_fn
{
    template<std::input_iterator I, no-throw-input-iterator O, no-throw-sentinel-for<O> S>
    requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
    ranges::uninitialized_copy_n_result<I, O>
    operator()(I ifirst, std::iter_difference_t<I> count, O ofirst, S olast) const
    {
        O current{ofirst};
        try
        {
            for (; count > 0 && current != olast; ++ifirst, ++current, --count)
                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;
        }
    }
};
 
inline constexpr uninitialized_copy_n_fn uninitialized_copy_n{};

[edit] Example

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
 
int main()
{
    const char* stars[]{"Procyon", "Spica", "Pollux", "Deneb", "Polaris"};
 
    constexpr int n{4};
    alignas(alignof(std::string)) char out[n * sizeof(std::string)];
 
    try
    {
        auto first{reinterpret_cast<std::string*>(out)};
        auto last{first + n};
        auto ret{std::ranges::uninitialized_copy_n(std::begin(stars), n, first, last)};
 
        std::cout << '{';
        for (auto it{first}; it != ret.out; ++it)
            std::cout << (it == first ? "" : ", ") << std::quoted(*it);
        std::cout << "};\n";
 
        std::ranges::destroy(first, last);
    }
    catch (...)
    {
        std::cout << "uninitialized_copy_n exception\n";
    }
}

Output:

{"Procyon", "Spica", "Pollux", "Deneb"};

[edit] See also

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