alper
alper

Reputation: 3390

variadic multidimensional array

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

Answers (2)

stardust
stardust

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

Here is a test run.


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

Tomek
Tomek

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

Related Questions