std::ranges::uninitialized_value_construct
Определено в заголовочном файле <memory> | ||
Сигнатура вызова | ||
template< прямой-итератор-без-исключения I, ограничитель-без-исключения-для<I> S > requires std::default_initializable<std::iter_value_t<I>> | (1) | (начиная с C++20) |
template< прямой-диапазон-без-исключения R > requires std::default_initializable<ranges::range_value_t<R>> | (2) | (начиная с C++20) |
[
first,
last)
, инициализацией значением, как если бы for(; first != last;++first)::new(static_cast<void*>(std::addressof(*first)))std::remove_reference_t<std::iter_reference_t<I>>();
Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Содержание |
[править]Параметры
first, last | — | пара итератор-ограничитель, обозначающая диапазон элементов для инициализации значением |
r | — | диапазон элементов для инициализации значением |
[править]Возвращаемое значение
Итератор, равный last.
[править]Сложность
Линейная по расстоянию между first и last.
[править]Исключения
Исключение, генерируемое при создании элементов в целевом диапазоне, если таковые имеются.
[править]Примечание
Реализация может повысить эффективность ranges::uninitialized_value_construct
, например используя ranges::fill, если тип значений диапазона TrivialTypeиCopyAssignable.
[править]Возможная реализация
struct uninitialized_value_construct_fn {template<прямой-итератор-без-исключения I, ограничитель-без-исключения-для<I> S> requires std::default_initializable<std::iter_value_t<I>> I operator()(I first, S last)const{using T =std::remove_reference_t<std::iter_reference_t<I>>;ifconstexpr(std::is_trivial_v<T>&&std::is_copy_assignable_v<T>)returnranges::fill(first, last, T()); I rollback{first};try{for(;!(first == last);++first)::new(const_cast<void*>(static_cast<constvolatilevoid*>(std::addressof(*first)))) T();return first;}catch(...)// откат: уничтожить созданные элементы{for(; rollback != first;++rollback)ranges::destroy_at(std::addressof(*rollback));throw;}} template<прямой-диапазон-без-исключения R> requires std::default_initializable<ranges::range_value_t<R>>ranges::borrowed_iterator_t<R> operator()(R&& r)const{return(*this)(ranges::begin(r), ranges::end(r));}}; inlineconstexpr uninitialized_value_construct_fn uninitialized_value_construct{}; |
[править]Пример
#include <iostream>#include <memory>#include <string> int main(){struct S {std::string m{"▄▀▄▀▄▀▄▀"};}; constexprint n{4}; alignas(alignof(S))char out[n * sizeof(S)]; try{auto first{reinterpret_cast<S*>(out)};auto last{first + n}; std::ranges::uninitialized_value_construct(first, last); auto count{1};for(auto it{first}; it != last;++it)std::cout<< count++<<' '<< it->m <<'\n'; std::ranges::destroy(first, last);}catch(...){std::cout<<"Исключение!\n";} // Обратите внимание, что для "тривиальных типов" uninitialized_value_construct// заполняет нулями заданную неинициализированную область памяти.int v[]{0, 1, 2, 3};std::cout<<' ';for(constint i : v)std::cout<<' '<<static_cast<char>(i +'A');std::cout<<"\n "; std::ranges::uninitialized_value_construct(std::begin(v), std::end(v));for(constint i : v)std::cout<<' '<<static_cast<char>(i +'A');std::cout<<'\n';}
Вывод:
1 ▄▀▄▀▄▀▄▀ 2 ▄▀▄▀▄▀▄▀ 3 ▄▀▄▀▄▀▄▀ 4 ▄▀▄▀▄▀▄▀ A B C D A A A A
[править]Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3870 | C++20 | этот алгоритм может создавать объекты в const хранилище | запрещено |
[править]Смотрите также
создаёт объекты инициализированные значением в неинициализированной области памяти, определяемой началом и количеством (ниблоид) | |
создаёт объекты инициализацией по умолчанию в неинициализированной области памяти, определяемой диапазоном (ниблоид) | |
создаёт объекты инициализацией по умолчанию в неинициализированной области памяти, определяемой началом и количеством (ниблоид) | |
создаёт объекты инициализацией значением в неинициализированной области памяти, определяемой диапазоном (шаблон функции) |