3

I tried to set array size with const member variable like below

class A {
  const int SIZE;

  A() : SIZE(10) {}
  void aaa() { int a[SIZE]; }
};

I cannot build

a[SIZE]

like this expression.

When I use GCC, build success. But when I use VC++ (Windows), I cannot build.

The error message is "'this' cannot be used in a constant expression"

How to set array size with const member variable?

Dayamre
  • 1,907
  • 2
  • 13
  • 10
  • https://stackoverflow.com/questions/39334435/variable-length-array-vla-in-c-compilers – user202729 Jan 18 '19 at 02:38
  • 1
    C++ need to know array sizes at compile time. Consider making your array size into a template parameter instead of a class member. – najayaz Jan 18 '19 at 02:52
  • SIZE variable is const variable but member variable. I already check to build with this expression in gcc. However only Visual C++ compiler cannot build with this expression. – Dayamre Jan 18 '19 at 02:56
  • Can you initialize the constant on the line `const int SIZE = 10;` ? – Baxter Jan 18 '19 at 03:33
  • 1
    `SIZE` is not a constant expression (it is just a const qualified int). If you’re using newer c++ standard versions, you can declare it to be constexpr instead of const and initialize it inline (`constexpr int SIZE = 10;`). – John Drouhard Jan 18 '19 at 04:21
  • Or use `static const int SIZE = 10;` – Remy Lebeau Jan 18 '19 at 04:53
  • Variable Length Array is a non-standard extension. Both compilers must have switched to turn this feature on/off. – zdf Jan 18 '19 at 07:09

3 Answers3

3

Variable Length Arrays

when I use VC++ (Windows), I cannot build.

An array int a[SIZE] is created on stack with automatic storage duration. Then this SIZE usually must be determined at compile-time in C++. But your SIZE is defined without a value as follows:

const int SIZE;

Thus compilers can not know it's value at compile-time and would show compilation error. So your SIZE is a dynamic variable.

When I use GCC, build success.

...But some C++ compilers support VLA (variable length arrays) which is a C99 addition and allows declaring C-style arrays on stack with a dynamic length. VC++ does not support C99 and VLA, but GNU compiler supports VLA as an extension even in C90 and C++. This is the reason why you can compile the above code by GCC without errors.

If you add -pedantic (-pedantic-errors) option to gcc compile command, we can get warnings (errors) for most gcc extensions. In this case, with this option we should get warning (error) message: ISO C++ forbids variable length array 'a'.


How to fix the current error ?

(1) If you want to use C-style arrays, one way is making SIZE a macro as follows. Then compilers can know it's value at compile-time:

#define SIZE 10

class A
{
public:
  A() {}
  void aaa() { int a[SIZE]; }
};

(2) Defining the value of SIZE as a static const variable in the class definition, then compilers again can know it's value at compile-time:

class A
{
  static constexpr int SIZE = 10;

public:
  A() {}
  void aaa() { int a[SIZE]; }
};

(3) C++ provides array functionality by std::vector and std::array which might make our code more readable, portable and robust. I expect that std::array on stack would be more efficient than std::vector in your case, because 10 ints need less memory and std::array is allocated on stack just only once without causing problems. This is a solution with std::array:

#include <array>

class A
{
  static constexpr int SIZE = 10;

public:
  A() {}
  void aaa() { std::array<int, SIZE> a; }
};
Hiroki
  • 2,780
  • 3
  • 12
  • 26
0

Well, SIZE is probably not a macro because, here, you initialize it with 10 and have it as a variable. If it was a macro, your expression int a[SIZE] would work but you would not need lines 2-4 anyways.

If SIZE is, as here, a normal variable (which includes dynamically creating A with a size parameter, although the input might be from a macro), you should use a vector.

#include <vector>

class A {
  const int SIZE;

  A() : SIZE(10) {}
  void aaa() { std::vector<int> a(SIZE); }
};

Usage of a is now the same.

IceFire
  • 4,016
  • 2
  • 31
  • 51
0

If you are using an older compiler pre c++11, e.g c++03 you can also do enum {SIZE=10};

class A {
  enum {SIZE=10};

  void aaa() {int a[SIZE];}
};
r0n9
  • 2,505
  • 1
  • 29
  • 43