std::ranges::uninitialized_copy_n, std::ranges::uninitialized_copy_n_result
| Определено в заголовочном файле <memory>
|
||
| Сигнатура вызова |
||
template< std::input_iterator I, итератор-ввода-без-исключения O, ограничитель-без-исключения-для<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) | (начиная с C++20) |
| Вспомогательные типы |
||
template< class I, class O > using uninitialized_copy_n_result = ranges::in_out_result<I, O>; |
(2) | (начиная с C++20) |
Пусть N будет ranges::min(count, ranges::distance(ofirst, olast)), создаёт N элементов в выходном диапазоне [ofirst, olast), который является неинициализированной областью памяти, из элементов входного диапазона, начиная с ifirst.
Входной диапазон [ifirst, ifirst + count) не должен перекрываться выходным диапазоном [ofirst, olast).
Если во время инициализации генерируется исключение, уже созданные объекты уничтожаются в неопределённом порядке.
Функция имеет эффект, эквивалентный:
auto ret = ranges::uninitialized_copy(std::counted_iterator(ifirst, count),
std::default_sentinel, ofirst, olast);
return {std::move(ret.in).base(), ret.out};
Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Параметры
| ifirst | — | начало диапазона элементов для копирования |
| count | — | количество элементов для копирования |
| ofirst, olast | — | пара итератор-ограничитель, обозначающая диапазон назначения |
Возвращаемое значение
{ifirst + N, ofirst + N}.
Сложность
𝓞(N).
Исключения
Исключение, возникающее при построении элементов в целевом диапазоне, если таковые имеются.
Примечание
Реализация может повысить эффективность ranges::uninitialized_copy_n, используя, например, ranges::copy_n, если тип значения выходного диапазона TrivialType.
Возможная реализация
struct uninitialized_copy_n_fn
{
template<std::input_iterator I, итератор-ввода-без-исключения O, ограничитель-без-исключения-для<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 (...) // откат: уничтожить созданные элементы
{
for (; ofirst != current; ++ofirst)
ranges::destroy_at(std::addressof(*ofirst));
throw;
}
}
};
inline constexpr uninitialized_copy_n_fn uninitialized_copy_n{};
|
Пример
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
int main()
{
const char* stars[]{ "Процион", "Спика", "Поллукс", "Денеб", "Полярис", };
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\n";
}
}
Вывод:
{"Процион", "Спика", "Поллукс", "Денеб"};
Смотрите также
(C++20) |
копирует диапазон объектов в неинициализированную область памяти (ниблоид) |
(C++11) |
копирует ряд объектов в неинициализированную область памяти (шаблон функции) |