Initializing multi-dimensional array in constructor

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jayharris@gmail.com

    Initializing multi-dimensional array in constructor

    I'm having a ton of trouble initializing a multi-dimensional array
    inside a constructor, largely because I don't know the size of the
    array until runtime. I have a class that looks like this:

    class MyClass
    {
    public:
    const int size;
    MyClass( const int );
    };

    MyClass::MyClas s( const int s )
    : size( s )
    {
    int (*arrayPtr)[size][size] = new int[size][size][size];
    }

    When I compile this with g++ (actually, Apple's version of g++, in case
    that matters), I get the following error:
    myclass.cpp : In constructor 'MyClass::MyCla ss(int)':
    myclass.cpp.8: error: 'MyClass::size' cannot appear in a
    constant-expression
    myclass.cpp.8: error: 'MyClass::size' cannot appear in a
    constant-expression

    Can anyone explain why I'm getting this error message, especially since
    size is declared const, and also can anyone help me out with what to do
    about it? Thanks.

    --Jay

  • Victor Bazarov

    #2
    Re: Initializing multi-dimensional array in constructor

    jayharris@gmail .com wrote:
    I'm having a ton of trouble initializing a multi-dimensional array
    inside a constructor, largely because I don't know the size of the
    array until runtime. I have a class that looks like this:
    >
    class MyClass
    {
    public:
    const int size;
    MyClass( const int );
    };
    >
    MyClass::MyClas s( const int s )
    : size( s )
    {
    int (*arrayPtr)[size][size] = new int[size][size][size];
    }
    >
    When I compile this with g++ (actually, Apple's version of g++, in
    case that matters), I get the following error:
    myclass.cpp : In constructor 'MyClass::MyCla ss(int)':
    myclass.cpp.8: error: 'MyClass::size' cannot appear in a
    constant-expression
    myclass.cpp.8: error: 'MyClass::size' cannot appear in a
    constant-expression
    >
    Can anyone explain why I'm getting this error message, especially
    since size is declared const, and also can anyone help me out with
    what to do about it? Thanks.
    Please see the FAQ. Creation of multidimensiona l dynamic arrays is
    actually covered in it.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • Frederick Gotham

      #3
      Re: Initializing multi-dimensional array in constructor

      Jay Harris posted:

      int (*arrayPtr)[size][size] = new int[size][size][size];

      You're going to need to employ more devious tactics, something like:

      (I've written this hastily in the last half hour, so expect bugs.)


      #include <cassert>

      template<class T>
      class Accessor2D {
      protected:

      T *const p;
      unsigned const d2;

      public:

      Accessor2D(T *const parg,unsigned const arg2) : p(parg), d2(arg2)
      {
      assert(parg);
      assert(arg2);
      }

      T *operator[](unsigned const arg2)
      {
      assert(arg2);

      return p + (arg2 * d2);
      }
      };


      template<class T>
      class Accessor3D {
      protected:

      T *const p;
      unsigned const d2;
      unsigned const d3;

      public:

      Accessor3D(T *const parg,unsigned const arg2, unsigned const arg3)
      : p(parg), d2(arg2), d3(arg3)
      {
      assert(parg);
      assert(arg2);
      assert(arg3);
      }


      Accessor2D<Tope rator[](unsigned const arg1)
      {
      assert(arg1);

      return Accessor2D<T>( p + (arg1 * d2 * d3), d3 );
      }
      };


      /* Now here comes your class */


      class MyClass {
      public:
      unsigned const size;
      MyClass(unsigne d const);
      };

      MyClass::MyClas s(unsigned const s) : size(s)
      {
      Accessor3D<inta rr(new int[size*size*size],size,size);

      arr[0][0][0] = 5;

      arr[0][1][2] = 7;
      }

      int main()
      {
      MyClass obj(7);
      }

      --

      Frederick Gotham

      Comment

      • Andrey Tarasevich

        #4
        Re: Initializing multi-dimensional array in constructor

        jayharris@gmail .com wrote:
        I'm having a ton of trouble initializing a multi-dimensional array
        inside a constructor, largely because I don't know the size of the
        array until runtime. I have a class that looks like this:
        "Size" portion of array types in C++ must be a so called 'integral constant
        expression' (ICE). The exact definition of ICE can be found in the language
        specification, but the idea is that the size must be known at compile time.
        Non-static class data members cannot be used in ICEs. This is what makes the
        compiler to complain.

        Since in your case array sizes are only known at run-time, there's no way to
        achieve what you want with array type or type derived from array type (as the
        'int (*)[size][size]' you are trying to use). There are different ways to solve
        the problem:

        1. Use a 1D array of size 'size * size * size' and simulate a 3D access by
        manually transforming the 3D indices into the corresponding the 1D index:

        [x][y][z] - [x * size * size + y * size + z]

        (that's, BTW, how built-in arrays work in C/C++)

        2. Use the well-known array-of-pointers idiom:

        int*** arrayPtr = new int**[size];
        // Then for each i
        arrayPtr[i] = new int*[size];
        // Then for each i, j
        arrayPtr[i][j] = new int[size];

        (the above is just an illustration of the idea; the actual implementation can be
        done in a neater way).

        3. (Might make the most sense out of three) Use
        'std::vector<st d::vector<std:: vector<int >'.
        class MyClass
        {
        public:
        const int size;
        MyClass( const int );
        };
        >
        MyClass::MyClas s( const int s )
        : size( s )
        {
        int (*arrayPtr)[size][size] = new int[size][size][size];
        }
        >
        When I compile this with g++ (actually, Apple's version of g++, in case
        that matters), I get the following error:
        myclass.cpp : In constructor 'MyClass::MyCla ss(int)':
        myclass.cpp.8: error: 'MyClass::size' cannot appear in a
        constant-expression
        myclass.cpp.8: error: 'MyClass::size' cannot appear in a
        constant-expression
        --
        Best regards,
        Andrey Tarasevich

        Comment

        • jayharris@gmail.com

          #5
          Re: Initializing multi-dimensional array in constructor

          Thanks. Option 1 seemed the simplest, so I went with it.

          Andrey Tarasevich wrote:
          jayharris@gmail .com wrote:
          I'm having a ton of trouble initializing a multi-dimensional array
          inside a constructor, largely because I don't know the size of the
          array until runtime. I have a class that looks like this:
          >
          "Size" portion of array types in C++ must be a so called 'integral constant
          expression' (ICE). The exact definition of ICE can be found in the language
          specification, but the idea is that the size must be known at compile time.
          Non-static class data members cannot be used in ICEs. This is what makes the
          compiler to complain.
          >
          Since in your case array sizes are only known at run-time, there's no way to
          achieve what you want with array type or type derived from array type (as the
          'int (*)[size][size]' you are trying to use). There are different ways to solve
          the problem:
          >
          1. Use a 1D array of size 'size * size * size' and simulate a 3D access by
          manually transforming the 3D indices into the corresponding the 1D index:
          >
          [x][y][z] - [x * size * size + y * size + z]
          >
          (that's, BTW, how built-in arrays work in C/C++)
          >
          2. Use the well-known array-of-pointers idiom:
          >
          int*** arrayPtr = new int**[size];
          // Then for each i
          arrayPtr[i] = new int*[size];
          // Then for each i, j
          arrayPtr[i][j] = new int[size];
          >
          (the above is just an illustration of the idea; the actual implementation can be
          done in a neater way).
          >
          3. (Might make the most sense out of three) Use
          'std::vector<st d::vector<std:: vector<int >'.
          >
          class MyClass
          {
          public:
          const int size;
          MyClass( const int );
          };

          MyClass::MyClas s( const int s )
          : size( s )
          {
          int (*arrayPtr)[size][size] = new int[size][size][size];
          }

          When I compile this with g++ (actually, Apple's version of g++, in case
          that matters), I get the following error:
          myclass.cpp : In constructor 'MyClass::MyCla ss(int)':
          myclass.cpp.8: error: 'MyClass::size' cannot appear in a
          constant-expression
          myclass.cpp.8: error: 'MyClass::size' cannot appear in a
          constant-expression
          >
          --
          Best regards,
          Andrey Tarasevich

          Comment

          Working...