Чтобы получить заданное вами c отображение:
auto test_vector = n_dim_vector_generator<2, long double>(2, 3)
на вектор 3x3, заполненный двумя, ваш шаблон может быть немного проще, если вы воспользуетесь этим конструктором vector
:
std::vector<std::vector<T>>(COUNT, std::vector<T>(...))
Так как vector
можно копировать, это заполнит слоты COUNT другой копией вектора. Итак ...
template <size_t N, typename T>
struct n_dim_vector_generator {
using type = std::vector<typename n_dim_vector_generator<N-1, T>::type>;
type operator()(T value, size_t size) {
return type(size, n_dim_vector_generator<N-1, T>{}(value, size));
}
};
template <typename T>
struct n_dim_vector_generator<0, T> {
using type = T;
type operator()(T value, size_t size) {
return value;
}
};
использование:
auto test_vector = n_dim_vector_generator<2, long double>{}(2, 3);
Демо: https://godbolt.org/z/eiDAUG
Для записи, по адресу некоторые замечания из комментариев: C ++ имеет идиоматический c, инициализируемый, непрерывный класс памяти, эквивалентный многомерному массиву C: вложенный std::array
:
std::array<std::array<long double, COLUMNS>, ROWS> test_array = { /*...*/ };
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
Если вы хотите уменьшить шаблон для объявления одного, вы можете использовать структуру для этого:
template <typename T, size_t... N>
struct multi_array;
template <typename T, size_t NFirst, size_t... N>
struct multi_array<T, NFirst, N...> {
using type = std::array<typename multi_array<T, N...>::type, NFirst>;
};
template <typename T, size_t NLast>
struct multi_array<T, NLast> {
using type = std::array<T, NLast>;
};
template <typename T, size_t... N>
using multi_array_t = typename multi_array<T, N...>::type;
Затем использовать:
multi_array_t<long double, ROWS, COLUMNS> test_array = { /*...*/ };
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
Это расположено в стеке, как массив C. Это, конечно, съест ваше пространство стека для большого массива. Но вы можете сделать диапазон декоратора около std::unique_ptr
, чтобы сделать указатель на него немного проще:
template <typename T, size_t... N>
struct dynamic_multi_array : std::unique_ptr<multi_array_t<T, N...>> {
using std::unique_ptr<multi_array_t<T, N...>>::unique_ptr;
constexpr typename multi_array_t<T, N...>::value_type& operator [](size_t index) { return (**this)[index]; }
constexpr const typename multi_array_t<T, N...>::value_type& operator [](size_t index) const { return (**this)[index]; }
constexpr typename multi_array_t<T, N...>::iterator begin() { return (**this).begin(); }
constexpr typename multi_array_t<T, N...>::iterator end() { return (**this).end(); }
constexpr typename multi_array_t<T, N...>::const_iterator begin() const { return (**this).begin(); }
constexpr typename multi_array_t<T, N...>::const_iterator end() const { return (**this).end(); }
constexpr typename multi_array_t<T, N...>::const_iterator cbegin() const { return (**this).cbegin(); }
constexpr typename multi_array_t<T, N...>::const_iterator cend() const { return (**this).cend(); }
constexpr typename multi_array_t<T, N...>::size_type size() const { return (**this).size(); }
constexpr bool empty() const { return (**this).empty(); }
constexpr typename multi_array_t<T, N...>::value_type* data() { return (**this).data(); }
constexpr const typename multi_array_t<T, N...>::value_type* data() const { return (**this).data(); }
};
(пусть покупатель остерегается, если вы используете эти методы с nullptr
)
Тогда вы все еще можете инициализировать выражение new
скобками и использовать его как контейнер:
dynamic_multi_array<long double, ROWS, COLUMNS> test_array {
new multi_array_t<long double, ROWS, COLUMNS> { /* ... */ }
};
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
Демонстрация: https://godbolt.org/z/lUwVE_