std::ranges::uninitialized_copy, std::ranges::uninitialized_copy_result
Определено в заголовочном файле <memory>
|
||
Сигнатура вызова |
||
template< std::input_iterator I, std::sentinel_for<I> S1, прямой-итератор-без-исключения O, ограничитель-без-исключения-для<O> S2 > |
(1) | (начиная с C++20) |
template< ranges::input_range IR, прямой-диапазон-без-исключения OR > requires std::constructible_from<ranges::range_value_t<OR>, |
(2) | (начиная с C++20) |
Вспомогательные типы |
||
template< class I, class O > using uninitialized_copy_result = ranges::in_out_result<I, O>; |
(3) | (начиная с C++20) |
[
ofirst,
olast)
, который является неинициализированной областью памяти, из элементов во входном диапазоне [
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); }
in_range
в качестве первого диапазона и out_range
в качестве второго диапазона, как при использовании ranges::begin(in_range) в качестве ifirst, ranges::end(in_range) в качестве ilast, ranges::begin(out_range) в качестве ofirst, а ranges::end(out_range) в качетсве olast.Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Содержание |
[править] Параметры
ifirst, ilast | — | пара итераторов ограничителей, обозначающая диапазон элементов, из которого следует копировать |
in_range | — | диапазон элементов для копирования |
ofirst, olast | — | пара итераторов ограничителей, обозначающая диапазон назначения |
out_range | — | диапазон назначения |
[править] Возвращаемое значение
{ifirst + N, ofirst + N}.
[править] Сложность
𝓞(N).
[править] Исключения
Исключение, возникающее при построении элементов в целевом диапазоне, если таковые имеются.
[править] Примечание
Реализация может повысить эффективность ranges::uninitialized_copy
, если тип значения выходного диапазона TrivialType.
[править] Возможная реализация
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 (...) // откат: уничтожить построенные элементы { 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{}; |
[править] Пример
#include <cstdlib> #include <iomanip> #include <iostream> #include <memory> #include <string> int main() { const char* v[]{ "Это", "пример", }; 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 << (it == first ? "" : ", ") << std::quoted(*it); std::cout << "};\n"; std::ranges::destroy(first, last); } catch (...) { std::cout << "исключение uninitialized_copy\n"; } std::free(pbuf); } }
Вывод:
{ "Это", "пример" };
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3870 | C++20 | этот алгоритм может создавать объекты в const хранилище | запрещено |
[править] Смотрите также
(C++20) |
копирует ряд объектов в неинициализированную область памяти (ниблоид) |
копирует диапазон объектов в неинициализированную область памяти (шаблон функции) |