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 .

6
  • How about my_array.size() * my_array[0].size() * my_array[0][0].size() * my_array[0][0][0].size()? Commented Jul 10, 2019 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) Commented Jul 10, 2019 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;? Commented Jul 10, 2019 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? Commented Jul 10, 2019 at 10:16
  • @vahancho I bet you because the OP looks for a solution that does not involve specific indices or number of dimensions. Commented Jul 10, 2019 at 10:19

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Is it possible that arr_sz<decltype(my_array)>::size / sizeof(arr_sz<decltype(my_array)>::value_type) is larger than the overall number of elements?
@PeterA.Schneider - Could be smaller if unsigned overflow occurred during the computation. Don't see how it could be larger.
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;
}

1 Comment

Interesting. This functional approach seems similar to StoryTeller's data approach.
2

How about

sizeof(my_array)/sizeof(double);

2 Comments

The question is probably whether the standard guarantees that.
@PeterA.Schneider it does not apparently: stackoverflow.com/questions/25173462/…
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{});
}

Comments

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;

2 Comments

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::arrays 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.
@PeterA.Schneider Fair point. I think StoryTeller just posted such a solution, it's indeed superior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.