# Generic multidimensional array in C++

#include <iostream>
#include <memory>
using std::cout;
using std::endl;

template<typename T, int dimension = 1>
class Array
{
private:
std::unique_ptr<T[]> pointer;
int size[dimension];
int realSize;

public:
Array()
{
}

template<typename... Ns>
Array(Ns... ns)
: realSize(1)
{
create(1, ns...);
}

private:
template<typename... Ns>
void create(int d, int n, Ns... ns)
{
realSize *= n;
size[d - 1] = n;
create(d + 1, ns...);
}

void create(int d)
{
pointer = std::unique_ptr<T[]>(new T[realSize]);
}

int computeSubSize(int d) const
{
if (d == dimension)
{
return 1;
}
return size[d] * computeSubSize(d + 1);
}

template<typename... Ns>
int getIndex(int d, int n, Ns... ns) const
{
return n * computeSubSize(d) + getIndex(d + 1, ns...);
}

int getIndex(int d) const
{
return 0;
}

public:
template<typename... Ns>
T& operator()(Ns... ns) const
{
return pointer[getIndex(1, ns...)];
}

int getSize(int d = 1) const
{
return size[d - 1];
}
};

int main()
{
constexpr int N = 10;
Array<int> a(N);
for (int i = 0; i < a.getSize(); ++i)
{
a(i) = i + 1;
cout << a(i) << ' ';
}
cout << '\n' << endl;
Array<int, 2> a2(N, N * 2);
for (int i = 0; i < a2.getSize(1); ++i)
{
for (int j = 0; j < a2.getSize(2); ++j)
{
a2(i, j) = i + j + 2;
if (a2(i, j) < 10)
{
cout << '0';
}
cout << a2(i, j) << ' ';
}
cout << endl;
}
return 0;
}


Output

1 2 3 4 5 6 7 8 9 10

02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21
03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22
04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

• int size[dimension]; - isn't this just the number of elements in a single-dimensional array? – Jamal Jun 20 '15 at 0:25
• @Jamal Yes it is. – xiver77 Jun 20 '15 at 0:28
• Then I don't understand the variable dimension here. – Jamal Jun 20 '15 at 0:29
• @Jamal It is the number of dimensions for the array. 1 for 1D, 2 for 2D, 3 for 3D and so on. – xiver77 Jun 20 '15 at 0:34
• @Jamal In a single-dimensional array, yes size[dimension] is just the number of elements, but in an n-dimensional array where n > 1, it stores the size for each dimension. – xiver77 Jun 20 '15 at 0:43

• No need for an empty constructor in C++11:

Array()
{
}


You can just use a default constructor:

Array() = default;

• It's a little confusing to have multiple public/private sections. Here, you can just put all the public code under the same keyword.

• You could make your structure more useful by providing iterators. This will, for instance, allow you to use range based for-loops instead of plain ones for iterating through this structure.

• You don't need std::endl if you just need newlines. Just output "\n" instead for this. More info about this can be found here.

• It's unnecessary to have your own return 0 at the end of main() in C++. The compiler will provide this return for you.

For your int template parameter, it makes no sense to have a signed dimension quantity. Use size_t as that parameter and update int to size_t in your code.

There are quite a few things :

• Naming your variables. I don't know why, the naming of your functions is quite good, but not the naming of your variables, why ? a, n, i, d, among others, deserve to have a real name, for readability.
• if (a2(i, j) < 10) I see what you're doing here but please don't do it that way. Using std::setfill and std::setw could do that for you. Or a good old printf
• for (int i = 0; i < a2.getSize(1); ++i) Is the size of a2 going to change inside the loop ? If not, there's no need to compute at each loop iteration.
• Not a single comment in all your code, that's a performance, but not a good one. If you want to make up for this, you could even use Doxygen-style comments, to be able to generate quickly some documentation, in addition to normal comments inside your complicated functions.
• cout << '\n' << endl; Not quite sure what you want to do there.