const defined as class member in another module

C

Christopher Pisz

I need to define the size of an array at compile time.

The size I need to use is a static constant unsigned long which is a
public class member in another library.

The compiler complains that "expected constant size"

If I try to use keyword extern, it compains that it is a class member
and I cannot use keyword extern on it.

I am not quite sure why the compiler does not think this is a constant
which is defined at compile time or how I can use it in my array
declaration. I could just allocate an array or use a std::vector, but
one must learn when one comes across things he does not understand.

Here is what I am trying

// When I include the header from the library, it is linked via
// compiler specific code.
#include "OtherClass.h"

int main()
{
unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
return 0;
}

----------------
Then in the other library:

In the OtherClass.h

namespace OtherNamespace
{
MyClass
{
public:
// REMOVED irrelevant code
static const unsigned int MAX;
};
}

--------------
In the OtherClass.cpp

namespace OtherNamespace
{
const unsigned int OtherClass::MAX_SIZE = 16;
}
 
K

K. Frank

Hello Christopher!

I need to define the size of an array at compile time.

The size I need to use is a static constant unsigned long which is a
public class member in another library.

The compiler complains that "expected constant size"

If I try to use keyword extern, it compains that it is a class member
and I cannot use keyword extern on it.

I am not quite sure why the compiler does not think this is a constant
which is defined at compile time or how I can use it in my array
declaration. I could just allocate an array or use a std::vector, but
one must learn when one comes across things he does not understand.

Here is what I am trying

// When I include the header from the library, it is linked via
// compiler specific code.
#include "OtherClass.h"

int main()
{
unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
return 0;
}

----------------
Then in the other library:

In the OtherClass.h

namespace OtherNamespace
{
MyClass
{
public:
// REMOVED irrelevant code
static const unsigned int MAX;
};
}

--------------
In the OtherClass.cpp

namespace OtherNamespace
{
const unsigned int OtherClass::MAX_SIZE = 16;
}

First comment:

The way you currently have things structured, the compiler
can't do what you want.

(I am assuming that the use of "MAX" instead of "MAX_SIZE"
in OtherClass.h is just a typo.)

The file -- the so-called "translation unit" -- in which
you are declaring myArray of size MAX_SIZE includes
OtherClass.h. So when the array declaration is being
compiled, the compiler could know that MAX_SIZE is a const
int. But the actual value of MAX_SIZE doesn't appear in
OtherClass.h, rather, it appears in OtherClass.cpp. The
compiler doesn't know about OtherClass.cpp when it's
compiling your first file (translation unit). (This is
by design.)

It's only at link time when you link your main program with
the object file produced by compiling OtherClass.cpp that
the value of MAX_SIZE becomes available to the overall program.

What you want to do is very common, and the poor man's
non-type-safe way to do it is to use a macro:

#define MAX_SIZE 16

But folks frown on that.

C++11 let's you (I'm pretty sure) do the following as one
of its new convenience features:

OtherClass.h:

MyClass {
public:
static const unsigned int MAX_SIZE = 16
};

Now OtherClass::MAX_SIZE is a nice, type-safe const int
that can be used in your declaration of myArray in your
main program.

That is:

#include "OtherClass.h"
unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];

is perfectly legal and does what you want.


Good luck.


K. Frank
 
K

K. Frank

Hi Paavo!

Nope, for integers this feature has been supported in all C++ versions,
precisely for the purpose of array declaration.

Thank you for this correction. (C++11 extends this feature to
non-integers and some other cases.)
Note that a separate definition in some .cpp file

const unsigned int OtherClass::MAX_SIZE;

is formally still needed.

I think (I'm a little foggy on exactly what the standard
says) that the separate definition is only required by the
standard if MAX_SIZE is used outside of constant expressions.
If not present, one may get linker errors
depending on the usage of this symbol, the compiler and its optimization
level.

hth
Paavo

Thanks.


K. Frank
 
V

Victor Bazarov

I need to define the size of an array at compile time.

The size I need to use is a static constant unsigned long which is a
public class member in another library.

The compiler complains that "expected constant size"

If I try to use keyword extern, it compains that it is a class member
and I cannot use keyword extern on it.

I am not quite sure why the compiler does not think this is a constant
which is defined at compile time or how I can use it in my array
declaration. I could just allocate an array or use a std::vector, but
one must learn when one comes across things he does not understand.

Here is what I am trying

// When I include the header from the library, it is linked via
// compiler specific code.
#include "OtherClass.h"

int main()
{
unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
return 0;
}

----------------
Then in the other library:

In the OtherClass.h

namespace OtherNamespace
{
MyClass

I think you meant

class OtherClass

here...
{
public:
// REMOVED irrelevant code
static const unsigned int MAX;

Use an enum instead.

enum { MAX_SIZE = 16 };

And there is no need to add anything there...
namespace OtherNamespace
{
const unsigned int OtherClass::MAX_SIZE = 16;
}

V
 
J

James Kanze

I need to define the size of an array at compile time.
The size I need to use is a static constant unsigned long which is a
public class member in another library.
The compiler complains that "expected constant size"
If I try to use keyword extern, it compains that it is a class member
and I cannot use keyword extern on it.
I am not quite sure why the compiler does not think this is a constant
which is defined at compile time or how I can use it in my array
declaration. I could just allocate an array or use a std::vector, but
one must learn when one comes across things he does not understand.
Here is what I am trying
// When I include the header from the library, it is linked via
// compiler specific code.
#include "OtherClass.h"
int main()
{
unsigned long myArray[OtherNamespace::OtherClass::MAX_SIZE];
return 0;
}
----------------
Then in the other library:
In the OtherClass.h
namespace OtherNamespace
{
MyClass
{
public:
// REMOVED irrelevant code
static const unsigned int MAX;
};
}
--------------
In the OtherClass.cpp
namespace OtherNamespace
{
const unsigned int OtherClass::MAX_SIZE = 16;
}
First comment:
The way you currently have things structured, the compiler
can't do what you want.

It could, and as it is worded, the standard actually says that
it has to. A more accurate statement would be that a classical
compiler couldn't do it, and the fact that the standard requires
it is probably an error in the standard, since there is a
definite intention that C++ not require anything beyond
classical compiler technology (although as it stands, templates
and inline functions also require a little be more).
(I am assuming that the use of "MAX" instead of "MAX_SIZE"
in OtherClass.h is just a typo.)
The file -- the so-called "translation unit" -- in which
you are declaring myArray of size MAX_SIZE includes
OtherClass.h. So when the array declaration is being
compiled, the compiler could know that MAX_SIZE is a const
int. But the actual value of MAX_SIZE doesn't appear in
OtherClass.h, rather, it appears in OtherClass.cpp. The
compiler doesn't know about OtherClass.cpp when it's
compiling your first file (translation unit). (This is
by design.)
It's only at link time when you link your main program with
the object file produced by compiling OtherClass.cpp that
the value of MAX_SIZE becomes available to the overall program.

Most modern compilers have options which defer the actual code
generation until link time. You can't really do effective
optimization otherwise. For various historical reasons, this
technology is only activated for optimization.
What you want to do is very common, and the poor man's
non-type-safe way to do it is to use a macro:
#define MAX_SIZE 16
But folks frown on that.

To the point where I've never seen it in C++ code.
C++11 let's you (I'm pretty sure) do the following as one
of its new convenience features:

MyClass {
public:
static const unsigned int MAX_SIZE = 16
};

You don't need C++11; that works in C++98. In pre-standard C++,
the usual solution was something like:

class MyClass
{
public:
enum { maxSize = 16 };
// ....
};

Not perfect, because the actual type is an unnamed enum type,
and not int, or size_t, or whatever. But it worked pretty well
in practice. (Also, of course: unless maxSize is a macro, it
won't be written in all caps.)
 
J

James Kanze

(e-mail address removed):
Nope, for integers this feature has been supported in all C++ versions,
precisely for the purpose of array declaration.

I've used C++ versions where it wasn't supported. It was
introduced in C++98. The first "standard", but C++ was around
before then.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top