Reputation: 3390
Could I call a multidimensional array like
func(0,0,0); //=> if I know it's dimension on the run time.
func(0,0,0,0,0,0,0,0,0,0,0); //=> if I know it's dimension on the run time.
through help of the variadic templates
instead of:
data[0][0][0];
data[0][0][0][0][0][0][0][0][0][0][0];
Upvotes: 2
Views: 791
Reputation: 5988
This should work but instead of doing data[1][2][3]
you will have to use indexed(data,1,2,3)
It works for plain arrays
as well as std::arrays
. You can extend it std::vector
just by duplicating the specializations. (I think it should work for any thing that overloads operator[] but not sure.)
#include <iostream>
#include <array>
template<typename T, size_t dim>
struct getTypeAtDim { typedef T type; };
template<typename T, size_t N>
struct getTypeAtDim<T[N],1> { typedef T type; };
template<typename T, size_t dim, size_t N>
struct getTypeAtDim<T[N],dim> : getTypeAtDim< T, dim-1> {};
template<typename T, size_t N>
struct getTypeAtDim<std::array<T,N>,1> { typedef T type; };
template<typename T, size_t dim, size_t N>
struct getTypeAtDim<std::array<T,N>,dim> : getTypeAtDim< T, dim-1> {};
template<typename T, size_t dim>
using typeAtDim = typename getTypeAtDim<T, dim>::type;
template<typename T>
typeAtDim<T,1>&
indexed(T& arr, const int& first) {
return arr[first];
}
template<typename T, typename... Args>
typeAtDim<T,sizeof...(Args) + 1>&
indexed(T& arr, const int& first, const Args& ...rest) {
return indexed(arr[first],rest...);
}
int main() {
std::array<int,2> a1 = {1,2};
std::array<int,2> a2 = {3,4};
std::array<std::array<int,2>,2> a = {a1,a2};
std::array<std::array<std::array<int,2>,2>,2> c = {a,a};
int b[2][2] = {{5,6},{7,8}};
std::cout << indexed(a,1,1) << std::endl;
indexed(a,1,1) = 5;
std::cout << indexed(a,1,1) << std::endl;
std::cout << indexed(b,1,1) << std::endl;
std::cout << indexed(c,1,1,1) << std::endl;
indexed(c,1,1) = a1;
std::cout << indexed(c,1,1,1) << std::endl;
}
4 5 8 4 2
I am not using auto
with trailing return types
because the variadic version of indexed
will not match itself when deducing the type of the return. So until that gets resolved with gcc
you will have to use something like this.
Upvotes: 4
Reputation: 4659
You can overload operator(). I am not sure if it is going to help you a lot.
If you are using C++11 you may think creatively about using initializer_list.
Upvotes: 0