Увеличение размера динамического массива, реализуемого на shared_ptr
Есть метод push_back для динамического массива.
void TVector::push_back(const Square& value) {
if(_size == 0){
auto _array = std::make_shared<std::array<Square, 1>>();
(*_array)[0] = value;
_size++;
}
else{
auto _array = std::make_shared<std::array<Square, _size>>();
(*_array)[_size] = value;
_size++;
}
}
Она работает когда размер нулевой, то есть динамический массив еще пустой, но как только размер становится единица и больше, не совсем понятно как выделять дополнительную память. На
auto _array = std::make_shared<std::array<Square, _size>>();
жалуется IDE таким образом Non-type template argument is not a constant expression.
Подскажите, есть ли какой-то способ похожий на realloc по смыслу для умного указателя shared_ptr, чтобы можно было реализовать данный метод.
Ответы (1 шт):
Всё сложно, тут одна из основных проблем темплейтов в C++.
Дело в том, что при компиле
std::array<Square, 1>
std::array<Square, 2>
std::array<Square, 3>
Компилятор генерит разный код для каждого из 3 типов. Для C++ это 3 совершенно различных типа. И такое не скомпилится:
std::shared_ptr<std::array<int, 4242>> p=std::make_shared<std::array<int, 42>>();
Но раз уж пошли таким путём, то если очень постараться, то можно запилить такое.
Для начала понадобится массив типов. https://stackoverflow.com/questions/24015710/for-loop-over-template-arguments-types
Массив соответственно из:
std::array<Square, 1>
std::array<Square, 2>
std::array<Square, 4>
std::array<Square, 8>
Можно и не кратные 2 если хочется.
Далее так как это всё разные типы, то нельзя просто так:
std::shared_ptr<std::array<int, 4242>> p=std::make_shared<std::array<int, 42>>();
Нам нужен либо variant, либо void
std::shared_ptr<std::variant<all_types array 1 2 4 8>>
std::shared_ptr<void>
Далее что-то типо такого:
std::variant<all_types array 1 2 4 8> make_shared_of(int size){
std::optional<std::variant<all_types array 1 2 4 8>> res;
for_<all_types array 1 2 4 8>([&]<typename T>(T* type_dummy){
if(!res && T().size() >= size)
res = T();
});
return *res;
}
void TVector::resize(int size) {
auto _array = make_shared_of(size);
_size = size;
// copy array data...
}
void TVector::push_back(const Square& value) {
resize(_size + 1);
std::visit([&](auto&& arg){arg[_size - 1] = value;}, array);
}
О том какого размер будет .exe, и как быстро компилиться, и работать я не буду упоминать.