std::ranges::uninitialized_fill
Материал из cppreference.com
Определено в заголовочном файле <memory> | ||
Сигнатура вызова | ||
template< прямой-итератор-без-исключения I, ограничитель-без-исключения-для<I> S, class T > requires std::constructible_from<std::iter_value_t<I>, const T&> | (1) | (начиная с C++20) |
template< прямой-диапазон-без-исключения R, class T > requires std::constructible_from<ranges::range_value_t<R>, const T&> | (2) | (начиная с C++20) |
1) Создаёт N копий заданного значения x в неинициализированной области памяти, обозначенной диапазоном
[
first,
last)
, гдн N это ranges::distance(first, last). Функция имеет эффект, эквивалентный:
for(; first != last;++first)::new(static_cast<void*>(std::addressof(*first)))std::remove_reference_t<std::iter_reference_t<I>>(x); return first;
Если во время инициализации генерируется исключение, уже созданные объекты уничтожаются в неопределённом порядке.
2) То же, что и (1), но использует r в качестве диапазона, как если бы использовались ranges::begin(r) как first, и ranges::end(r) как last.
Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Содержание |
[править]Параметры
first, last | — | пара итератор-ограничитель, обозначающая диапазон элементов для инициализации |
r | — | диапазон элементов для инициализации |
value | — | значение, с которым создавать элементы |
[править]Возвращаемое значение
Итератор, равный last.
[править]Сложность
𝓞(N).
[править]Исключения
Исключение, возникающее при создании элементов в целевом диапазоне, если таковые имеются.
[править]Примечание
Реализация может повысить эффективность ranges::uninitialized_fill
, например, с помощью ranges::fill, если тип значения выходного диапазона TrivialType.
[править]Возможная реализация
struct uninitialized_fill_fn {template<прямой-итератор-без-исключения I, ограничитель-без-исключения-для<I> S, class T> requires std::constructible_from<std::iter_value_t<I>, const T&> I operator()(I first, S last, const T& x)const{ I rollback{first};try{for(;!(first == last);++first)ranges::construct_at(std::addressof(*first), x);return first;}catch(...){// откат: уничтожить созданные элементыfor(; rollback != first;++rollback)ranges::destroy_at(std::addressof(*rollback));throw;}} template<прямой-диапазон-без-исключения R, class T> requires std::constructible_from<ranges::range_value_t<R>, const T&>ranges::borrowed_iterator_t<R> operator()(R&& r, const T& x)const{return(*this)(ranges::begin(r), ranges::end(r), x);}}; inlineconstexpr uninitialized_fill_fn uninitialized_fill{}; |
[править]Пример
Запустить этот код
#include <iostream>#include <memory>#include <string> int main(){constexprint n{4}; alignas(alignof(std::string))char out[n * sizeof(std::string)]; try{auto first{reinterpret_cast<std::string*>(out)};auto last{first + n}; std::ranges::uninitialized_fill(first, last, "▄▀▄▀▄▀▄▀"); int count{1};for(auto it{first}; it != last;++it)std::cout<< count++<<' '<<*it <<'\n'; std::ranges::destroy(first, last);}catch(...){std::cout<<"Исключение!\n";}}
Вывод:
1 ▄▀▄▀▄▀▄▀ 2 ▄▀▄▀▄▀▄▀ 3 ▄▀▄▀▄▀▄▀ 4 ▄▀▄▀▄▀▄▀
[править]Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3870 | C++20 | этот алгоритм может создавать объекты в const хранилище | запрещено |
[править]Смотрите также
(C++20) | копирует объект в неинициализированную область памяти, определяемую началом и количеством (ниблоид) |
копирует объект в неинициализированную область памяти, определяемую диапазоном (шаблон функции) |