0

Is it possible for a class to have a member which is a multidimensional array whose dimensions and extents are not known until runtime?

I have found (via this guide) a way to create a struct to easily nest std::arrays at compile time using template metaprogramming:

#include <array>
/*
this struct allows for the creation of an n-dimensional array type
*/
template <typename T,size_t CurrentDimExtent,size_t... NextDimExtent>
struct MultiDimArray{
public:
//define the type name nestedType to be a recursive template definition.
  using nestedType=typename MultiDimArray<T,NextDimExtent...>::type;
  using type=std::array<nestedType,CurrentDimExtent>;
};
/*
This struct is the template specialization which handles the base case of the
 final dimensional extent
*/
template <typename T,size_t DimExtent>
struct MultiDimArray<T,DimExtent>{
  using type=std::array<T,DimExtent>;
};

this still falls short of satisfying my requirement in two ways (that I know of):

  1. In order to declare a variable (or a pointer to a variable) of this type you must state the dimensions.
  2. This only works when the DimExtents are constant expressions (set at compile time).

To demonstrate why number 2 is a distinct problem, here is a class with a set number of dimensions (2) using a void* to reference the multidimensional array:

template <typename T>
class TwoDimGrid{
public:
TwoDimGrid(const size_t extent1,const size_t extent2):
 _twoDimArray(new MultiDimArray<T,extent1,extent2>);
private:
void* _twoDimArray;
};

This will not compile as extent1 and extent2 are not constant expressions.

other notes:

  • I would like to see if it's possible to accomplish using std:array, rather than native arrays or a dynamically resizing container like std::vector.
  • Please use smart pointers where appropriate (I didn't as I'm not really sure how to handle a smart void pointer).

Edit

I have fallen into the trap of The XY Problem with X being the first sentence of this question and Y being how to accomplish it with std::array. I therefore created a new question and am leaving this one here in case it's ever possible to solve Y problem.

Community
  • 1
  • 1
Key Lay
  • 366
  • 3
  • 13
  • std::array needs to know its size in compile time, you can't have it deduce it in runtime, use std::vector – dchhetri Nov 26 '13 at 02:25
  • @user814628 even using std::vector, I would still run into the problem of having to know the number of dimensions at compile time. – Key Lay Nov 26 '13 at 02:28
  • 1
    Can you use boost::multi_array? – dchhetri Nov 26 '13 at 02:30
  • @user814628 oh, yes. That's what I'll do. I am still curious as to how it can be done. I wonder how they did it... – Key Lay Nov 26 '13 at 02:38
  • @KyléBoltón http://www.boost.org/doc/libs/1_55_0/libs/multi_array/doc/reference.html –  Nov 26 '13 at 02:42

2 Answers2

0

old school multidimensional arrays, something along these lines:

template <typename T>
class multi
{
   T*myArray;
   size_t x_dim;
   size_t y_dim;
public:
   multi(size_t x, size t y) : x_dim(x), y_dim(y)
   {
        myArray = new T[x*y];
   }

   T& get(int x, int y)
   {
       return myArray[x*y_dim+y];
   }
};
Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
  • This code doesn't create a multidimensional array but mimics a 2D array. A multidimensional array needs an undefined number of parameters: T& get(x1,x2,x3,.....,xN). – lucas92 Nov 28 '13 at 14:19
0
template <typename T>
class vvc
{
    //possible ragged array ..non rigorous approach
    //with management memory cost per element
    //clearly not as efficient as .... linearized access where access index is
    //row size * r + column
    //memory management courtesy of vector
    public:
    std::vector< std::vector<T> > v;
};

int double_vector()
{
    int x1 = 5;
    int x2 = 3;
    std::vector<int> r(x2);
    vvc<int> vv;
    int k = 0;
    for (int i1 = 0; i1 < x1; ++i1)
    {
        for (int i2 = 0; i2 < x2; ++i2)
        {
            k += 1;
            r[i2] = k;
        }
        vv.v.push_back(r);

    }
    //inspect
    cout << vv.v[0][0] << " first " << endl;
    for (auto const & t1 : vv.v)
    {
        for (auto const &t2 : t1 )
        {
            cout << t2 << " ";
        }
        cout << endl;
    }
    return 0;
}
VIRTUAL-VOID
  • 279
  • 1
  • 11