Вариативный шаблон для многомерного std :: array - PullRequest
0 голосов
/ 05 октября 2018

Мы можем создать псевдоним многомерного массива следующим образом:

template<typename T, size_t size1, size_t size2>
using myArray = std::array<std::array<T, size2>, size1>;

Но это позволяет нам только заранее определенное количество измерений.Есть ли способ превратить это в шаблон с переменным числом, чтобы мы могли написать любой из них:

myArray<int, 2, 2, 2> arr3d;
myArray<int, 2, 2, 2, 2> arr4d;

Я пробовал несколько вещей, но не был полностью удовлетворен ни одним из них.

Это:

template<typename T, size_t size>
using myArray<T, size> = std::array<T, size>;

template<typename T, size_t size, size_t... more>
using myArray = std::array<myArray<T, more...>, size>;

даже не компилируется, поскольку специализации шаблонов явно не разрешены для шаблонов псевдонимов.

В настоящее время это мое лучшее решение, но удаляются все конструкторы std:: массив, который я хотел бы сохранить:

template<typename T, size_t size, size_t... more>
struct myArray : public std::array<myArray<T, more...>, size> {};

template<typename T, size_t size>
struct myArray<T, size> : public std::array<T, size>{};

И с этим решением мне всегда нужно было бы писать ".internal" перед каждым доступом к массиву:

template<typename T, size_t size, size_t... more>
struct myArr {
    std::array<myArr<T, more...>, size> internal;
};

template<typename T, size_t size>
struct myArr<T, size> {
    std::array<T, size> internal;
};

Так могКто-нибудь думает о решении, как второе, но где я могу оставить конструкторов?Я не могу.

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Вы можете использовать дополнительный слой:

template<typename T, size_t size, size_t... more>
struct myArray_impl
{
    using type = std::array<typename myArray_impl<T, more...>::type, size>;
};

template<typename T, size_t size>
struct myArray_impl<T, size>
{
    using type = std::array<T, size>;
};

template<typename T, size_t size, size_t... more>
using myArray = typename myArray_impl<T, size, more...>::type;
0 голосов
/ 05 октября 2018

Я бы предложил просто умножить размеры вместе и получить один std::array.Например: std::array<int, D0 * D1 * D2 * D3>.Затем можно предоставить служебные функции или класс-оболочку для преобразования многомерного индекса в одномерный.

В любом случае ...

Вот простое рекурсивное решение, использующее явную специализацию шаблона:

template <typename T, std::size_t... Ds>
struct nested_array;

template <typename T, std::size_t D>
struct nested_array<T, D>
{
    using type = std::array<T, D>;
};

template <typename T, std::size_t D, std::size_t... Ds>
struct nested_array<T, D, Ds...>
{
    using type = std::array<typename nested_array<T, Ds...>::type, D>;
};

static_assert(std::is_same_v<
    typename nested_array<int, 1, 2, 3>::type,
    std::array<std::array<std::array<int, 3>, 2>, 1>
>);

живой пример на wandbox


Вот решение, основанное на частичной специализации переменного шаблона:

template <typename T>
struct t { using type = T; };

template <typename T>
using unwrap = typename T::type;

template <typename T, std::size_t... Ds>
constexpr auto nested_array = t<void>{};

template <typename T, std::size_t D>
constexpr auto nested_array<T, D> = t<std::array<T, D>>{};

template <typename T, std::size_t D, std::size_t... Ds>
constexpr auto nested_array<T, D, Ds...> = 
    t<std::array<unwrap<decltype(nested_array<T, Ds...>)>, D>>{};

static_assert(std::is_same_v<
    unwrap<decltype(nested_array<int, 1, 2, 3>)>,
    std::array<std::array<std::array<int, 3>, 2>, 1>
>);

живой пример на wandbox

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...