C ++ 17 добавляет std::destroy_at
, но нет std::construct_at
аналога. Почему это? Разве это не может быть реализовано так просто, как показано ниже?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args) {
return new (addr) T(std::forward<Args>(args)...);
}
Что позволило бы избежать этого не совсем естественного размещения нового синтаксиса :
auto ptr = construct_at<int>(buf, 1); // instead of 'auto ptr = new (buf) int(1);'
std::cout << *ptr;
std::destroy_at(ptr);
std::construct_at
был добавлен к C++ 20. Бумага, которая сделала так, [еще 119] constexpr контейнеры . По-видимому, это, как замечалось, не имело достаточно преимуществ перед размещением, новым в C++ 17, но C++ 20 вещей изменений.
цель предложения, которое добавило эту опцию, состоит в том, чтобы поддерживать constexpr выделения памяти, включая std::vector
. Это требует способности создать объекты в выделенное устройство хранения данных. Однако просто новые соглашения размещения с точки зрения void *
, не T *
. constexpr
оценка в настоящее время не имеет никакой способности получить доступ к необработанному устройству хранения данных, и комитет хочет сохранить это тем путем. Библиотечная функция std::construct_at
добавляет введенный интерфейс constexpr T * construct_at(T *, Args && ...)
.
Это также имеет преимущество не требования, чтобы пользователь указал создаваемый тип; это выведено из типа указателя. Синтаксис для корректного вызова размещения новым является довольно ужасающим и парадоксальным. Сравните std::construct_at(ptr, args...)
::new(static_cast<void *>(ptr)) std::decay_t<decltype(*ptr)>(args...)
.