std::ranges::uninitialized_copy() 算法
- 自 C++20 起
- 简化
- 详细
// (1)
uninitialized_copy_result<I, O>
uninitialized_copy( I ifirst, S1 ilast, O ofirst, S2 olast );
// (2)
uninitialized_copy_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_copy( IR&& in_range, OR&& out_range );
参数类型是泛型的,并具有以下约束:
I
-std::input_iterator
S1
,S2
-std::sentinel_for<I>
,no-throw-sentinel-for<O>
O
-no-throw-forward-iterator
IR
-ranges::input_range
OR
-no-throw-forward-range
此外,每个重载都有以下约束
- (1)
std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
- (1)
std::constructible_from<ranges::range_value_t<OR>, ranges::range_reference_t<IR>>
// (1)
template<
std::input_iterator I,
std::sentinel_for<I> S1,
no-throw-forward-iterator O,
no-throw-sentinel-for<O> S2
>
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
uninitialized_copy_result<I, O>
uninitialized_copy( I ifirst, S1 ilast, O ofirst, S2 olast );
// (2)
template<
ranges::input_range IR,
no-throw-forward-range OR
>
requires std::constructible_from<ranges::range_value_t<OR>,
ranges::range_reference_t<IR>>
uninitialized_copy_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_copy( IR&& in_range, OR&& out_range );
辅助类型定义如下:
template< class I, class O >
using uninitialized_copy_result = ranges::in_out_result<I, O>;
-
(1) 令
N
为ranges::min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast))
:在输出范围 [ofirst
;olast
) 中构造N
个元素,该范围是未初始化的内存区域,从输入范围 [ifirst
;ilast
) 中的元素复制。重要输入和输出范围不得重叠。
注意如果在初始化期间抛出异常,则已构造的对象将以未指定顺序销毁。
此函数的效果等同于
for (; !(ifirst == ilast || ofirst == olast); ++ofirst, ++ifirst)
{
::new (static_cast<void*>(std::addressof(*ofirst)))
std::remove_reference_t<std::iter_reference_t<O>>(*ifirst);
} -
(2) 与 (1) 相同,但使用
in_range
作为第一个范围,out_range
作为第二个范围,如同使用ranges::begin(in_range)
作为ifirst
,ranges::end(in_range)
作为ilast
,ranges::begin(out_range)
作为ofirst
,以及ranges::end(out_range)
作为olast
。
本页描述的函数类实体是niebloids。
参数
ifirst ilast | 要复制的元素范围。 |
in_range | 要复制的元素范围。 |
ofirst olast | 目标范围。 |
out_range | 目标范围。 |
返回值
{
ifirst + N,
ofirst + N
}
复杂度
给定 N
为 ranges::min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast))
O(N)
异常
构造目标范围中的元素时抛出的异常(如果有)。
可能的实现
uninitialized_copy(1) 和 uninitialized_copy(2)
struct uninitialized_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S1,
no-throw-forward-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{};
备注
如果输出范围的值类型是 TrivialType
,则实现可以提高 ranges::uninitialized_copy
的效率。
示例
#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);
}
}
{ "This", "is", "an", "example", };