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) |
создаёт объект по заданному адресу (шаблон функции) |