3

I am having a multidimensional std::array and looking for the proper (convenient and efficient) way to find its size (in number of cells or in bytes)

size() returns only the last dimension size (which is understood)

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

my_array.size();  // returns 100

Although the size of the array is known in compile time, I wish to avoid #define SIZE_OF_MY_ARRAY or a global variable because, I am looking for a better way than passing the size with the array (as in "old" arrays, not std array), or informing others to use the defined term.

I also prefer no to calculate it every time.

Perhaps these 2 preferences are not possible for multidimensional array?

How can I efficiently find the overall size of my_array? I am using .

JeJo
  • 30,635
  • 6
  • 49
  • 88
Micha
  • 33
  • 6
  • How about `my_array.size() * my_array[0].size() * my_array[0][0].size() * my_array[0][0][0].size()`? – Blaze Jul 10 '19 at 10:07
  • size in bytes is `sizeof(my_array)`, size in cells is `my_array.size()`, amount of doubles is `sizeof(my_array) / sizeof(double)` – user7860670 Jul 10 '19 at 10:10
  • To be honest, I don't get the problem. If you know the sizes of all arrays at compile time, why can't you simply multiply them, i.e. `size = 2 * 3 * 6 * 100;`? – vahancho Jul 10 '19 at 10:11
  • Isn't the idea that `std::array` has "no hair" (no extraneous information, just like built-in arrays), i.e. `sizeof(my_array)/sizeof(double)` yields the element count? – Peter - Reinstate Monica Jul 10 '19 at 10:16
  • @vahancho I bet you because the OP looks for a solution that does not involve specific indices or number of dimensions. – Peter - Reinstate Monica Jul 10 '19 at 10:19
  • Thanks everyone for your comments. I edited the question to answer some of what your wrote and for others that will find this question in the future – Micha Jul 10 '19 at 10:32

5 Answers5

3

It's not too hard to write a small utility that calculates this at compile time.

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;
};

The above should unravel a nested array definition of any practical depth, and evaluate to the size in bytes used for storing T's, with all potential padding excluded.

An example of using it would be

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, ""); 

That you may see live.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
3

You can use a recursion to calculate its size:

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;
}
Coral Kashri
  • 3,436
  • 2
  • 10
  • 22
2

How about

sizeof(my_array)/sizeof(double);
Arne
  • 1,293
  • 1
  • 7
  • 20
2

Something similar to @KorelK 's approach. Recursive template function will stop when class template of std::array is primitive type.

(See online)

#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{});
}
JeJo
  • 30,635
  • 6
  • 49
  • 88
1

You could use constexpr variables that bind to the dimensions and then use those to compute the desired quantity.

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;
lubgr
  • 37,368
  • 3
  • 66
  • 117
  • 1
    I suppose the OP wanted to extract the constants *from the array* and find a general solution which can e.g. be written as a template function which works with all `std::array`s regardless of their specific sizes or number of dimensions. Your solution would also replace the `size()` member function which is obviously useful, but works only for the last dimension. – Peter - Reinstate Monica Jul 10 '19 at 10:21
  • @PeterA.Schneider Fair point. I think StoryTeller just posted such a solution, it's indeed superior. – lubgr Jul 10 '19 at 10:26