3

I want to write a loop, that can give me the dimensions of an array. I want to make it usable for any array and it should return the sizes of the dimensions.

int arr[3][5][10][9] ;
cout << "dimension 1: " << sizeof(arr)/sizeof(arr[0]) << endl; 
cout << "dimension 2: " << sizeof(arr[0])/sizeof(arr[0][0]) << endl; 
cout << "dimension 3: " << sizeof(arr[0][0])/sizeof(arr[0][0][0]) << endl;
cout << "dimension 4: " << sizeof(arr[0][0][0])/sizeof(arr[0][0][0][0]) << endl;
cout << "dimension 5: " << sizeof(arr[0][0][0][0])/sizeof(arr[0][0][0][0][0]) << endl;

This should return 3,5,10,9 (and fail for the last statement).

So the pattern seems clear "each iteration add [0] after arr. The last iteration will fail, which should stop the while-loop.

How can I "concatenate + evaluate" the array name?

I would also appreciate help on what test checks "Will this fail?", or "Is there another dimension?" in C++, as I'm just learning it.

Hope
  • 143
  • 11
  • 1
    `sizeof` is an operator, not a function, so you can write `sizeof x` to get the size of `x`. Putting `x` in brackets is redundant. That said, how should the last statement of yours "fail"? In any case, the way to go forward is to use templates, because the whole information about the sizes is contained in the type of `arr`. You can then use recursion to process each level of the array. For that, you will need to distinguish whether the remainder is still an array as stop condition. – Ulrich Eckhardt Mar 13 '19 at 06:13
  • What do you plan to do with this loop? If you place it in a function so you can reuse it, many things will go wrong, not the least [array decay](https://stackoverflow.com/questions/1461432/what-is-array-decaying) and the code not being able to compile. – user4581301 Mar 13 '19 at 06:14
  • Also there are many better tools than arrays in C++. You can even build yourself a class that is a multidimensional array with an arbitrary number of dimensions. Or use [`boost::multi-array`](https://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html) because they did all the work already. – user4581301 Mar 13 '19 at 06:22
  • @user4581301 I think classes would work well for me. However for my code runtime will be quite an important factor. My guess would've been, that arrays will run faster and produce smaler files when saving. Since C++ is more made for classes, do you think they might have an advantage over arrays here? – Hope Mar 13 '19 at 06:56
  • Yes, using `std::array` (when you know the bounds) or `std::vector` (when you don't) is likely to be *identical* performance to using `[N]` or `new [n]` – Caleth Mar 13 '19 at 09:32

1 Answers1

3

if you are using c++ 17 compiler, you can use type traits structs std::rank and std::extent as following

#include <iostream>
#include <type_traits>

template<typename T>
void print_dimension(std::size_t i) {
    if (std::rank_v<T> > 0) {
        std::cout << "Dimension " << i << ":" << std::extent_v<T> << std::endl;
        print_dimension<typename std::remove_extent_t<T>>(i + 1);
    }
}

int main() {
int arr[3][5][10][9] ;
print_dimension<decltype(arr)>(1);
return 0;
}

If you are using C++ 11/14 compiler, it would need slight modification

#include <iostream>
#include <type_traits>

template<typename T>
void print_dimension(std::size_t i) {
    if (std::rank<T>::value > 0) {
        std::cout << "Dimension " << i << ":" << std::extent<T>::value << std::endl;
        print_dimension<typename std::remove_extent<T>::type>(i + 1);
    }
}

int main() {
int arr[3][5][10][9] ;
print_dimension<decltype(arr)>(1);
return 0;
}
Nishant Singh
  • 4,177
  • 1
  • 17
  • 17
  • @Hope This approach uses templates, so it might be hard to understand if you just started learning c++ but you can ask if you are not able to understand something written in the code – Nishant Singh Mar 13 '19 at 06:39