менее подробный способ объявления многомерного std :: array - PullRequest
17 голосов
/ 07 октября 2011

Короткий вопрос: Есть ли более короткий способ сделать это

array<array<atomic<int>,n>,m> matrix;

Я надеялся на что-то вроде

array< atomic< int>,n,m> matrix;    

но это не работает ...

Ответы [ 5 ]

32 голосов
/ 07 октября 2011

Псевдоним шаблона может помочь:

#include <array>

template <class T, unsigned I, unsigned J>
using Matrix = std::array<std::array<T, J>, I>;

int main()
{
    Matrix<int, 3, 4> matrix;
}
31 голосов
/ 07 октября 2011

Обходное решение для компиляторов, которые еще не поддерживают псевдонимы шаблонов, - это использование простой метафункции для генерации типа:

#include <cstddef>
#include <array>

template<class T, std::size_t RowsN, std::size_t ColumnsN>
struct Matrix
{
    typedef std::array<std::array<T, ColumnsN>, RowsN> type; // row major

private:
    Matrix(); // prevent accidental construction of the metafunction itself
};

int main()
{
    Matrix<int, 3, 4>::type matrix;
}
12 голосов
/ 08 октября 2011

Решение с использованием шаблонов переменных (немного более сложное, чем псевдоним шаблона, но более общего назначения)

template <typename T, std::size_t thisSize, std::size_t ... otherSizes>
class multi_array : private std::array<multi_array<T, otherSizes...>, thisSize>
{
 using base_array = std::array<multi_array<T, otherSizes...>, thisSize>;

 public:
    using base_array::operator[];
    // TODO: add more using statements to make methods
    // visible.  This is less typing (and less error-prone)
    // than forwarding to the base_array type.
};

template <typename T, std::size_t thisSize>
class multi_array<T, thisSize> : private std::array<T, thisSize>
{
 using base_array = std::array<T, thisSize>;

 public:
    using base_array::operator[];
    // TODO: add more using statements to make methods
    // visible.  This is less typing (and less error-prone)
    // than forwarding to the base_array type.
};

Возможно, будет несколько улучшено назначение не-листьев массива, которые могут быть сделаны.

Я тестировал с относительно недавней сборкой clang / LLVM.

Наслаждайтесь!

11 голосов
/ 29 октября 2011

При вложении std :: array может стать очень трудным для чтения и излишне многословным. Противоположный порядок размеров может быть особенно запутанным.

Например:

std::array < std::array <int, 3 > , 5 > arr1; 

по сравнению с

char c_arr [5][3]; 

Также обратите внимание, что begin (), end () и size () все возвращают бессмысленные значения, когда вы вкладываете std :: array.

По этим причинам я создал свои собственные контейнеры многомерного массива фиксированного размера, array_2d и array_3d. У них есть преимущество в том, что они работают с C ++ 98.

Они аналогичны std :: array, но для многомерных массивов 2 и 3 измерения. Они безопаснее и имеют не худшую производительность, чем встроенные многомерные массивы. Я не включил контейнер для многомерных массивов с размерами, превышающими 3, поскольку они встречаются редко. В C ++ 11 можно создать версию шаблона с переменным числом аргументов, которая поддерживает произвольное количество измерений (что-то вроде примера Майкла Прайса).

Пример двумерного варианта:

//Create an array 3 x 5 (Notice the extra pair of braces) 
fsma::array_2d <double, 3, 5> my2darr = {{ 
{ 32.19, 47.29, 31.99, 19.11, 11.19}, 
{ 11.29, 22.49, 33.47, 17.29, 5.01 }, 
{ 41.97, 22.09, 9.76, 22.55, 6.22 } 
}};  

Полная документация доступна здесь: http://fsma.googlecode.com/files/fsma.html

Вы можете скачать библиотеку здесь: http://fsma.googlecode.com/files/fsma.zip

2 голосов
/ 26 мая 2012

Вот простая, общая версия:

template <typename T, size_t d1, size_t d2, size_t... ds>
struct GetMultiDimArray
{
    using type = std::array<typename GetMultiDimArray<T, d2, ds...>::type, d1>;
};

template <typename T, size_t d1, size_t d2>
struct GetMultiDimArray<T, d1, d2>
{
    using type = std::array<std::array<T, d2>, d1>;
};

template <typename T, size_t d1, size_t d2, size_t... ds>
using MultiDimArray = typename GetMultiDimArray<T, d1, d2, ds...>::type;

// Usage:
MultiDimArray<int, 3, 2> arr {1, 2, 3, 4, 5, 6};
assert(arr[1][1] == 4);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...