6
\$\begingroup\$
#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
\$\endgroup\$
5
  • \$\begingroup\$ int size[dimension]; - isn't this just the number of elements in a single-dimensional array? \$\endgroup\$
    – Jamal
    Jun 20, 2015 at 0:25
  • \$\begingroup\$ @Jamal Yes it is. \$\endgroup\$
    – user97096
    Jun 20, 2015 at 0:28
  • \$\begingroup\$ Then I don't understand the variable dimension here. \$\endgroup\$
    – Jamal
    Jun 20, 2015 at 0:29
  • \$\begingroup\$ @Jamal It is the number of dimensions for the array. 1 for 1D, 2 for 2D, 3 for 3D and so on. \$\endgroup\$
    – user97096
    Jun 20, 2015 at 0:34
  • \$\begingroup\$ @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. \$\endgroup\$
    – user97096
    Jun 20, 2015 at 0:43

3 Answers 3

8
\$\begingroup\$
  • 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.

\$\endgroup\$
2
\$\begingroup\$

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.
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.