Это продолжение моего ответа на вопрос об инициализации массивов конструктивных типов, отличных от стандартных.
Суть вопроса можно сформулировать в этом фрагменте, который представляет собой чрезмерное упрощение реального варианта использования, указанного выше:
#include
#include
#include
#include
#include
#include
// #define USE_CONSTEXPR
// Before C++23 I'm wrapping my pointer in a home-made struct with a delete []
// in the destructor
template
struct MyArrPtr {
T* ptr;
constexpr ~MyArrPtr() { ::delete[] ptr; };
};
template
constexpr std::array make_array(Generator gen) {
constexpr std::size_t RequiredSize = sizeof(std::array);
MyArrPtr Storage(new std::byte[RequiredSize]);
// std::array implicitely createad there
// unique_ptr could be used for triggering deallocation after the final
// std::move but actually usable in constexpr context only from C++23
// !!! This isn't allowed in constant evaluated context !!!
std::array* const Array =
std::launder(reinterpret_cast(Storage.ptr));
// initializing objects in the storage
T* it = Array->data();
for (std::size_t i = 0; i != N; ++i) {
// !!! not sure if placement new is allowed in constant evaluated context
// otherwise std::construct_at can be used !!!
new (it) T(gen(static_cast(i)));
++it;
}
// moving to force contained objects move
return std::move(*Array);
}
int main() {
constexpr std::size_t N = 50000;
auto gen = [](int i) { return i * i; };
#ifdef USE_CONSTEXPR
constexpr std::array arr = make_array(gen);
#else
std::array arr = make_array(gen);
arr[10] = 2;
#endif
std::cout
Подробнее здесь: [url]https://stackoverflow.com/questions/79811020/making-the-non-trivial-creation-an-array-constexpr[/url]
Это продолжение моего ответа на вопрос об инициализации массивов конструктивных типов, отличных от стандартных. Суть вопроса можно сформулировать в этом фрагменте, который представляет собой чрезмерное упрощение реального варианта использования, указанного выше: [code]#include #include #include #include #include #include
// #define USE_CONSTEXPR
// Before C++23 I'm wrapping my pointer in a home-made struct with a delete [] // in the destructor template struct MyArrPtr { T* ptr; constexpr ~MyArrPtr() { ::delete[] ptr; }; };
template constexpr std::array make_array(Generator gen) { constexpr std::size_t RequiredSize = sizeof(std::array); MyArrPtr Storage(new std::byte[RequiredSize]); // std::array implicitely createad there // unique_ptr could be used for triggering deallocation after the final // std::move but actually usable in constexpr context only from C++23
// !!! This isn't allowed in constant evaluated context !!! std::array* const Array = std::launder(reinterpret_cast(Storage.ptr));
// initializing objects in the storage T* it = Array->data(); for (std::size_t i = 0; i != N; ++i) {
// !!! not sure if placement new is allowed in constant evaluated context // otherwise std::construct_at can be used !!! new (it) T(gen(static_cast(i))); ++it; } // moving to force contained objects move return std::move(*Array); }
int main() { constexpr std::size_t N = 50000; auto gen = [](int i) { return i * i; }; #ifdef USE_CONSTEXPR constexpr std::array arr = make_array(gen); #else std::array arr = make_array(gen); arr[10] = 2; #endif std::cout