5
\$\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 '15 at 0:25
  • \$\begingroup\$ @Jamal Yes it is. \$\endgroup\$ – xiver77 Jun 20 '15 at 0:28
  • \$\begingroup\$ Then I don't understand the variable dimension here. \$\endgroup\$ – Jamal Jun 20 '15 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\$ – xiver77 Jun 20 '15 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\$ – xiver77 Jun 20 '15 at 0:43
7
\$\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\$

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\$
1
\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.