std::ranges::construct_at
Определено в заголовочном файле <memory>
|
||
Сигнатура вызова |
||
template< class T, class... Args > constexpr T* construct_at( T* p, Args&&... args ); |
(начиная с C++20) | |
Создаёт объект T
, инициализированный аргументами args... по заданному адресу p. construct_at
участвует в разрешении перегрузки, только если ::new(std::declval<void*>()) T(std::declval<Args>()...) корректно в неоценённом контексте.
return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
construct_at
может быть использована при вычислении константных выражений.
Когда construct_at
вызывается при вычислении некоторого константного выражения e, аргумент p должен указывать на хранилище, полученное std::allocator<T>::allocate или объект, время жизни которого началось при вычислении e.
Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Содержание |
[править] Параметры
p | — | указатель на неинициализированное хранилище, по которому будет создан объект T
|
args... | — | аргументы, используемые для инициализации |
[править] Возвращаемое значение
p
[править] Возможная реализация
struct construct_at_fn { template<class T, class...Args> requires requires (void* vp, Args&&... args) { ::new (vp) T(static_cast<Args&&>(args)...); } constexpr T* operator()(T* p, Args&&... args) const { return std::construct_at(p, static_cast<Args&&>(args)...); } }; inline constexpr construct_at_fn construct_at{}; |
[править] Примечание
std::ranges::construct_at
ведёт себя точно так же, как std::construct_at, за исключением того, что она невидима для поиска, зависящего от аргумента.
[править] Пример
#include <iostream> #include <memory> struct S { int x; float y; double z; S(int x, float y, double z) : x{x}, y{y}, z{z} { std::cout << "S::S();\n"; } ~S() { std::cout << "S::~S();\n"; } void print() const { std::cout << "S { x=" << x << "; y=" << y << "; z=" << z << "; };\n"; } }; int main() { alignas(S) unsigned char buf[sizeof(S)]; S* ptr = std::ranges::construct_at(reinterpret_cast<S*>(buf), 42, 2.71828f, 3.1415); ptr->print(); std::ranges::destroy_at(ptr); }
Вывод:
S::S(); S { x=42; y=2.71828; z=3.1415; }; S::~S();
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3870 | C++20 | construct_at может создавать объектыcv-квалифицированных типов |
разрешены только cv-квалифицированные типы |
[править] Смотрите также
(C++20) |
уничтожает объект по заданному адресу (ниблоид) |
(C++20) |
создаёт объект по заданному адресу (шаблон функции) |