2

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];
2
  • 2
    You want to create an array, or get an element from it? Commented May 21, 2013 at 17:10
  • More details or a use case would be helpful. Not really sure why/what you're trying to do. Commented May 21, 2013 at 18:07

2 Answers 2

4

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.

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

1 Comment

@Avatar Glad it helped. Actually I might even use it myself. Easier than doing [][] all the time in generated code. So thank you too for bringing up the idea :)
0

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.

Comments

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.