0

I was writting some class that map specific multidimensionnal array to unidimensionnal array (like 2D array N by M size is like a 1D array NM size you know, and then you can accees the cell [n, m] through [n+mN]). And it was quite boring since I must handle any multidimensional array (forced to copy/paste many times the class definition).

And I found something that could be great in my case: variadic template function. I would like to have my constructor and accessors using variadic template so my accessors can use any number of parameters (2 for 2D array, 3 for 3D array...) and same for my constructor, since I need to save the size in each dimension (N, M, ...) and multiply then to have the size of my unidimentionnal array.

The problem is that I don't know how to do that :( Every examples I found relies on two functions, one with one parameter of type T and another one with one parameter of type T and the Args... args).

Is it possible in one function ? Without recursion or so ? I gave you what I've made so far:

template <typename T, typename... Args>
T returner(T v, Args... args){
    return v;
}

template <typename T>
class Array{

    public:
    int* dim; //contain the size of each dimension
    T* array; //the actual array

    template<typename... Args>
    Array(Args... args){
        constexpr int size = sizeof...(Args);
        dim = new int[size];
        for(int i=0; i<size; i++)
            dim[i] = returner(args...);
            /*dim[0] should be equal to the first argument, dim[1]
            should be equal to the second argument and so on */
    }
};

int main(){
    Array<int>(2,2,2); // meant to be a 3D array, 2cells in each dimension
    return 0:
}

Obviously, "returner" always return the first argument and I understand why, but the only solution I see it to pass the dim array as a parameter and I would like to not do that. Is there a solution ??

PS: I could do that with classical variadic function, like in C, but it would be quite bad in performance :(

2
  • 1
    Could you show us an example where you try to create an Array (what do you pass as Args... typically?)? Because I don't understand what you are trying to do here... Commented Jan 26, 2017 at 13:32
  • I edited my message, hoping it answers your questions. Commented Jan 26, 2017 at 13:35

1 Answer 1

2

This should do what you want (if I understood correctly):

template <typename T>
class Array{

    public:
    int* dim; //contain the size of each dimension
    T* array; //the actual array

    template<typename... Args>
    Array(Args... args){
        constexpr int size = sizeof...(Args);
        dim = new int[size]{args...};
    }
};

But you'd better use std::vector instead of raw pointers - It would save you a lot of troubles:

template <typename T>
class Array{

    public:
    std::vector<int> dim; //contain the size of each dimension
    std::vector<T> array; //the actual array

    template<typename... Args>
    Array(Args... args) : dim{args...} {

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

10 Comments

Yeaaah :) Thanks, didnt thought i would initialize an array this way actually... thanks ;)
@Viridya You should probably use std::vector here for both dim and array, it would save you a lots of trouble.
@Viridya Is this really what you want? I took your question to mean if you use Array<int>(2,2,2) then the size should be 8, not 3 correct?
@Viridya You can loop, or std::accumulate(std::begin(dim), std::end(dim), 1, std::multiplies<>{}) (assuming you are using std::vector).
@Viridya In some cases it is more generic to use begin(dim) (without std:: actually), so that the code works if dim is a standard container, a raw array (int [4]), or a user defined container with a begin function. In this case, it does not change anything ;) See stackoverflow.com/questions/26290316/….
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.