Как найти размер многомерного std :: array? - PullRequest
3 голосов
/ 10 июля 2019

Я имею многомерный std::array и ищу правильный (удобный и эффективный) способ найти его размер (по количеству ячеек или в байтах)

size() возвращает только последний размерный размер (который понимается)

std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;

my_array.size();  // returns 100

Хотя размер массива известен во время компиляции, я хотел бы избежать #define SIZE_OF_MY_ARRAY или глобальной переменной, потому что я ищу лучший способ, чем передавать размер с массивом (как в «старых» массивах, не стандартный массив) или информирование других лиц об использовании определенного термина.

Я также предпочитаю не рассчитывать его каждый раз.

Возможно, эти 2 предпочтения невозможны для многомерного массива?

Как мне эффективно найти общий размер my_array? Я использую .

Ответы [ 5 ]

3 голосов
/ 10 июля 2019

Нетрудно написать небольшую утилиту, которая вычисляет это во время компиляции.

template<typename T> struct arr_sz {
    static constexpr std::size_t size = sizeof(T);
};

template<typename T, std::size_t N>
struct arr_sz<std::array<T, N>> {
    static constexpr std::size_t size = N * arr_sz<T>::size;
};

Вышеприведенное должно раскрыть определение вложенного массива любой практической глубины и привести к размеру в байтах, используемому для хранения T, с исключением всех возможных заполнений.

Примером его использования будет

std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;
constexpr auto sz = arr_sz<decltype(my_array)>::size;
static_assert(sz == sizeof(double) * 2 * 3 * 6 * 100, ""); 

Что вы можете увидеть вживую .

2 голосов
/ 10 июля 2019

Вы можете использовать рекурсию для расчета ее размера:

template<typename T>
size_t get_array_full_size(T &val) { // for the last array type (double in this case)
    return 1;
}

template<typename T, size_t Len>
size_t get_array_full_size(std::array<T, Len> &arr) {
    return get_array_full_size(arr[0]) * arr.size();
}

int main() {
    std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;
    std::cout << get_array_full_size(my_array) << std::endl;
    return 0;
}
2 голосов
/ 10 июля 2019

Как насчет

sizeof(my_array)/sizeof(double);
1 голос
/ 10 июля 2019

Что-то похожее на подход @ KorelK . Функция рекурсивного шаблона остановится, когда Шаблон класса std::array имеет примитивный тип .

( смотреть онлайн )

#include <array>
#include <type_traits> // std::is_fundamental_v

template<typename Type, std::size_t N>
std::size_t overall_size(const std::array<Type, N>&)
{
    if constexpr(std::is_fundamental_v<Type>)   return N;
    else return N * overall_size(Type{});
}
1 голос
/ 10 июля 2019

Вы можете использовать constexpr переменные, которые привязываются к измерениям, а затем использовать их для вычисления желаемого количества.

constexpr int n1 = 2;
constexpr int n2 = 3;
constexpr int n3 = 6;
constexpr int n4 = 100;

std::array<std::array<std::array<std::array<double, n1>, n2>, n3>, n4> my_array;

constexpr int myArraySize = n1*n2*n3*n4;
...