Однострочный инициализатор для Boost.MultiArray
У меня есть n-мерный Boost.MultiArray, который я инициализирую следующим образом:
const int n=3, size=4; //# of dimensions and size of one dimension
boost::multi_array<char,n> arr;
boost::array<size_t,n> extents; //size of each dimension
extents.assign(size); //assign size to each dimension -> {{4, 4, 4}}
arr.resize(extents);
Итак, у меня есть 4 строки кода для получения MultiArray, но я бы хотел сделать это в одну строку. Есть ли простой способ создания MultiArray с n измерениями, каждое из которых имеет size
длина (так что я могу написать arr(samevaluearray(n,size))
) или я пропустил удобный конструктор для MultiArray?
Редактировать: он должен работать без зависимости от определенного значения n, т.е. arr({{size,size}}
будет работать только для n=2
,
Так как может быть не понятно boost::multi_array<char,n>(boost::extents[4][4][4])
правильно инициализирует массив 4x4x4, но каждый раз n
изменяется в исходном коде, каждая инициализация должна обновляться вручную, поэтому это не вариант.
3 ответа
Оказывается, std::vector
имеет конструктор, который создает вектор с постоянным значением, повторяемым n раз, поэтому возможное решение выглядит следующим образом:
const int n=2, size=4; //# of dimensions and size of one dimension
boost::multi_array<char,n> arr(std::vector<size_t>(n,size));
Это инициализирует n-мерный multi_array с размером каждого измерения, равным size.
Вы можете инкапсулировать создание массива во вспомогательную функцию:
template <typename T, size_t N>
boost::multi_array<T, N> make_regular_matrix(const size_t m)
{
boost::multi_array<T, N> arr;
boost::array<size_t, N> extents;
extents.assign(m);
arr.resize(extents);
return arr;
}
const int n = 3;
int size = 4; // Can be const as well, but this is not mandatory
auto arr = make_regular_matrix<char, n>(size);
Если вы не можете использовать auto
Вам нужно будет продублировать параметры шаблона:
boost::multi_array<char, n> arr = make_regular_matrix<char, n>(size);
make_regular_matrix
функция может быть сокращена для использования std::vector
, как вы сделали в своем ответе; Я не знаю, будет ли эта реализация лучше. Цель вспомогательной функции - скрыть создание массива, но могут быть написаны другие версии, например, для инициализации элементов массива с заданным значением:
template <size_t N, typename T> //switched order for deduction
boost::multi_array<T, N> make_regular_matrix(const size_t m, const T & value)
{
boost::multi_array<T, N> arr(std::vector<size_t>(n, m));
std::fill(arr.data(), arr.data() + arr.num_elements(), value);
return arr;
}
auto arr = make_regular_matrix<4>(3, 'z'); //creates a 3x3x3x3 matrix
//filled with 'z's
Да, из документации Boost Multi-Array вы можете инициализировать его одной строкой:
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
Typedefs предназначены для удобства чтения, так же легко можно сделать для вашего примера:
boost::multi_array<int, 2> arr(boost::extents[2][4]);