Using static const + const as array bound
Asked Answered
W

2

13

I'm doing something like this

Class.hpp:

 class Class {

 private:
     static const unsigned int arraySize;
     int ar[arraySize+2];
 };

Class.cpp:

#include <Class.hpp>
const unsigned int arraySize = 384;

The compiler (q++, a c++ compiler for the QNX OS based on g++) gives me error: array bound is not an integer constant while compiling a unit including Class.hpp (not while compiling Class.cpp).

Why isn't that working? I know that a static const member can be used as an array bound, guaranteed by the C++ standard (see this anwser). But why doesn't the compiler see the result of static const + const as a constant?

Wieland answered 20/1, 2012 at 8:26 Comment(3)
Compiles fine for me (gcc 4.6.1), as it should. Probably a bug in that compiler?Convoy
I updated my example to better match my real code. Maybe there is an issue with the forward declaration of arraySize?Wieland
Please see here: DR#721. It was always intended (and in C++11 is explicitly the case) that the initializer for the constant should be visible at the point at which the static data member or constant variable was used for it to qualify as a constant expression.Helaine
B
13

This is good code which should have been accepted by the compiler:

class Class { 
  const static int arraySize = 384; 
  int ar[arraySize+2]; 
}; 

and if it isn't, your compiler is broken.

However, if you move actual constant out of the header file to selected translation unit, that invalidates the code.

// Class.h
class Class { 
  const static int arraySize;
  int ar[arraySize+2]; // ERROR
}; 

// Class.cpp
const int Class::arraySize = 384;

This is because the size of your Class object cannot be determined at compile time from the data available in the header alone. This is not exactly right reason, but reasoning along these lines helps to understand compilation errors such as this.

To avoid making such mistakes, you can replace static const int with an enum, e.g.

class Class { 
  enum { arraySize = 384 }; 
  int ar[arraySize+2]; 
}; 
Bomb answered 20/1, 2012 at 8:35 Comment(3)
Thanks for the workaround. I knew it myself. But it is important for me to check if this is valid C++ code. If you are right, then we might fill in a complaint against the company that sold us the compiler.Wieland
Oh, you changed to code in your question. Moving constant away from the header changes things entirely. I will update my answer to avoid misleading others.Bomb
Thanks. Sorry for the confusion.Wieland
E
2

I'm surprised this actually compiles on gcc, as a comment says. Since the 384 isn't in the header file, the size of the Class is not known to other compilation units. It might not matter in some compilation units depending on how/if they are using Class, but I can't imagine this compiling:

// this is a source file called, say, blah.cpp
#include <Class.hpp>

void someFunc()
{
    void *mem = malloc(sizeof(Class));  // size is not known, so this can't compile

    // do something with mem
}

You need to have in your .hpp:

class Class {

 private:
     static const unsigned int arraySize = 384;
     int ar[arraySize+2];
 };

.. as it is in the OP that you link to here.

Egeria answered 20/1, 2012 at 8:45 Comment(2)
OP change the question. Originally, the constant was defined in the header.Cybil
Comments refer to an earlier version of the example code in my question. However, if I'm defining my static const directly in the header, it compiles fine. So you might edit your answer and I will accept it. :)Wieland

© 2022 - 2024 — McMap. All rights reserved.