static const member initialization problem

Pages: 12
I am having a problem concerning a static const member variable I want to use to set a certain property of my class during development time. The question actually concerns proper implementation as I do have a solution that "works" at least. The variable should denote the size of a member array which I don't want to allocate on the heap due to serious performance issues. So here is my code:

1
2
3
4
5
6
7
8
9
//MyClass.h

class MyClass{
    public:
	static const int MyArraySize = 256;

    private:
        int MyArray[MyArraySize];
};


This works but it's not nice for two reasons:

1) It doesn't separate interface from implementation. I would prefer to define the variable in the corresponding .cpp file but it doesn't work:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//MyClass.h

class MyClass{
    public:
	static const int MyArraySize;
        static const int MyValue;

    private:
        int MyArray[MyArraySize];
};

//MyClass.cpp
#include "MyClass.h"

const int MyClass::MyArraySize = 256;
const int MyClass::MyValue = 100;


If I delete the line int MyArray[MyArraySize]; the above code works but when I use it to define the size of the array I get a "constant expression expected" error for the line int MyArray[MyArraySize]; which makes sense as the compiler does not know the value of MyArraySize when he reaches int MyArray[MyArraySize]; and therefore can not allocate the memory. Of course I can move MyArray to the heap like that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//MyClass.h

class MyClass{
    public:
	static const int MyArraySize;
        static const int MyValue;

        MyClass();
        ~MyClass();

    private:
        int* MyArray;
};

//MyClass.cpp
#include "MyClass.h"

const int MyClass::MyArraySize = 256;
const int MyClass::MyValue = 100;

MyClass::MyClass(){
    MyArray = new int(MyArraySize);
}

MyClass::~MyClass(){
    delete[] MyArray;
}


But as I mentioned before this causes a remarkable loss of performance.

2)
Something like the following does not work:

1
2
3
4
5
6
7
8
9
//MyClass.h

class MyClass{
    public:
	static const int MyArraySize = (int) pow(2, 8);

    private:
        int MyArray[MyArraySize];
};


This gives a "constant expression expected" error for the line static const int MyArraySize = (int) pow(2, 8);

Interestingly the following code works:

1
2
3
4
5
6
7
8
9
10
11
//MyClass.h

class MyClass{
    public:
        static const int MyValue;
};

//MyClass.cpp
#include "MyClass.h"

const int MyClass::MyValue = (int) pow(2, 8);


So if I use pow outside of the class definition I get no errors. Is there any solution to those problems? So what I want is:
1) Don't allocate the array on the heap
2) Separate interface from implementation
3) Being able to use functions like pow to define MyArraySize
4) Not use global variables

Thanks in advance for any help!
Last edited on
The first version looks fine to me. If you change the size of that array, you have changed the interface.
Yes, but the first version does not separate interface from implementation (as MyArraySize is declared and defined in the header file but should be defined in the corresponding source file) and I can't use functions (like pow) to define MyArraySize.
If the function that you are going to use is defined with constexpr specifier then there is no problem. As for the function pow() then you should define it yourself with the constexpr specifier that you can use its value as the size of the array.
This would solve the functions problem but constexpr is not supported by many compilers (e.g. the compiler that comes with Visual C++ 2012 does not support it) and there would still be the interface and implementation thing. Is there no way I can define MyArraySize anywhere but at the declaration and still use it to define the size of a non-heap array with it? Is there no "proper" way to do such a thing?
You can define the constant static data member as private.
You mean like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//MyClass.h

class MyClass{
    public:
        static const int MyValue;

    private:
        static const int MyArraySize;
        int MyArray[MyArraySize];
};

//MyClass.cpp
#include "MyClass.h"

const int MyClass::MyArraySize = 256;
const int MyClass::MyValue = 100;


?
That doesn't work either. It doesn't compile and throws the same error no matter if MyArraySize is public or private.
Old C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
template < unsigned int N, unsigned int P > struct cpow
{ enum { value = cpow<N,P-1>::value * N }; };
 
template < unsigned int N > struct cpow<N,0>
{ enum { value = 1 }; };
 
struct A
{
    int my_array[ cpow<2,8>::value ] ;
};
 
int main()
{
    std::cout << sizeof(A) << '\n' ;
}

http://ideone.com/CXVP2F
@mario0815
Defining a static constant data member as private does not mean that it shall be initialized outside the class.

So I meant only what I said.
@vlad from moscow: I see but as I need to know the size of the array outside of the class I defined it public.

@JL Borges: Nice method which allows to use at least certain kinds of "functions" (even if you have to reimplement them)

Still I'm not quite happy that I have to assign a value to the variable in the header file. Seems that there is no way to do it in the source file (or anywhere but at the declaration for that matter)
> Still I'm not quite happy that I have to assign a value to the variable in the header file.
> Seems that there is no way to do it in the source file (or anywhere but at the declaration for that matter)

If the size of an array is not a constant known at compile time, do the sensible thing - use std::vector<>.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <vector>
#include <cmath>

struct A // C++11
{
    std::vector<int> my_array { std::size_t( std::pow(2,8) ) } ;
};

struct B // also C++98
{
    B() : my_array( std::size_t( std::pow(2,8) ) ) {}

    std::vector<int> my_array ;
};
You can define a public method that will return the size. For example

1
2
3
4
5
6
7
class MyClass{
    public:
	int size() const { return MyArraySize; }

    private:
	static const int MyArraySize = 256;
};

Or if the array traps the number of its elemenrs then

1
2
int max_size() const { return MyArraySize; }
int size() const { return CurrentSize; }

@ JL Borges:
But vector does allocate the memory on the heap which I don't want as it reduces the performance considerably in my case. Actually that I want to use functions to define the constant is not my main concern. I just don't want to assign a value at declaration but do it just as in this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//MyClass.h

class MyClass{
    public:
	static const int MyArraySize;

    private:
        int MyArray[MyArraySize];
};

//MyClass.cpp
#include "MyClass.h"

const int MyClass::MyArraySize = 256;


So I assign the obviously constant value 256 to MyArraySize in the source file which is fine as long as I don't use it to define the array. There seems to be no way to let the compiler know what the value of MyArraySize is when the array is defined other than assigning the value directly at the declaration of MyArraySize.
Still I'm not quite happy that I have to assign a value to the variable in the header file. Seems that there is no way to do it in the source file (or anywhere but at the declaration for that matter)


This is correct and the way it has to be. Part of the reason for class declarations is to allow the compiler to know how much space to allocate on the stack or heap for the object. If your class contains an array, the declaration of the class must know the size of the array so the proper amount of memory can be allocated.
> There seems to be no way to let the compiler know what the value of MyArraySize is
> when the array is defined other than assigning the value directly at the declaration of MyArraySize.

Yes, no way other than by initializing MyArraySize with a constexpr. The size of an array must be a constant known at compile time.

In this case, to be able to create objects of type MyClass, the compiler must know (at compile time) sizeof(MyClass) even if it has only seen the class definition in the header header file.

If all objects of type MyClass are to be created with a dynamic storage duration, and inheriting from MyClass is disabled, there is a work-around.
I understand that but why can't I let the compiler know that the variable is defined elsewhere? I just tried out something similar:

1
2
3
4
5
6
7
8
9
10
11
//c.cpp
int MyArraySize = 256;

//d.cpp
extern int MyArraySize;

int main(){
    int MyArray[MyArraySize];
    
    return(0);
}

This works.

1
2
3
4
5
6
7
8
9
10
11
//c.cpp
int MyArraySize = 256;

//d.cpp
extern int MyArraySize;

int MyValue = MyArraySize;

int main(){
    return(0);
}

This works too.

1
2
3
4
5
6
7
8
9
10
11
//c.cpp
int MyArraySize = 256;

//d.cpp
extern int MyArraySize;

int MyArray[MyArraySize];

int main(){    
    return(0);
}


This does not work! Note that the only difference between this and the first example is that the array is defined globally. So if I define it locally in main the compiler finds the value of MyArraySize. If I use it to initialize a global variable it also finds the value. But if I use it to define a global array it does not!
mario0815, you need to disable non-standard compiler extensions to get sensible results in this case. For GCC, the option is -pedantic-errors
@Cubbi:
I tried adding the command but the last example still doesn't compile.
Add -std=C++98 (or -std=C++11) and -pedantic-errors and the first example won't compile.
Ah, the -pedantic-errors command ADDS pedantic errors and doesn't remove them! Didn't get that right ;)
Last edited on
Pages: 12