Discussion:
Definition of static const member var. when var is given a value in the class definition
(too old to reply)
A. McKenney
2011-06-13 08:58:47 UTC
Permalink
I'm getting a warning message from a compiler for
a construct that I thought was required by the standard.


In A.h (included in mulitple files):

class XXX { public: static const int DefaultX = 1; }; //
declaration of XXX::DefaultX

In A.cpp:

const int XXX::DefaultX; // definition of XXX::DefaultX

With VC++ 2010, this results in a multiply-defined
warning message for XXX::DefaultX.

If I comment out the definition (in A.cpp),
everything compiles fine & without errors.

(The Solaris 10 compiler is happy either way.)

My understanding of the standard was
that the definition is required.

Am I wrong? Or is VC++ wrong?

FWIW, if I move the "= 1" from the declaration to the
definition, it compiles w/o error under VC++.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Daniel Krügler
2011-06-13 22:44:10 UTC
Permalink
Post by A. McKenney
I'm getting a warning message from a compiler for
a construct that I thought was required by the standard.
class XXX { public: static const int DefaultX = 1; }; //
declaration of XXX::DefaultX
const int XXX::DefaultX; // definition of XXX::DefaultX
With VC++ 2010, this results in a multiply-defined
warning message for XXX::DefaultX.
This compiler diagnostics is very unfortunate and should not occur in a
good quality compiler unless the definition of XXX::DefaultX in A.cpp is
not the only one. Are you sure that you have not provided more than one
such definition? Have you possibly *included* A.cpp in another
translation unit?

It is definitively correct that

const int XXX::DefaultX;

is the correct way to *define* XXX::DefaultX, therefore this definition
is only optional unless your program does not ODR-use XXX::DefaultX.

According to [class.static.data] p2:

"The declaration of a static data member in its class definition is not
a definition [..] The definition for a static data member shall appear
in a namespace scope enclosing the member's class definition."

and p3 which describes the special case of const and non-volatile
literal type used as static data meber that has an initializer at the
in-class declaration (that is your case):

"[..] The member shall still be defined in a namespace scope if it is
odr-used (3.2) in the program and the namespace scope definition shall
not contain an initializer."
Post by A. McKenney
If I comment out the definition (in A.cpp),
everything compiles fine& without errors.
(The Solaris 10 compiler is happy either way.)
My understanding of the standard was
that the definition is required.
Well, the definition is required, if the program ODR-uses the variable,
but I would consider above warning as very misleading, because you
usually don't know, whether somewhere in the future the variable might
be odr-used, if it currently is not.
Post by A. McKenney
Am I wrong? Or is VC++ wrong?
If your program really provides a single definition of the static data
member as you describe above I consider this a compiler defect.

HTH & Greetings from Bremen,

- Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Fred
2011-06-13 22:46:06 UTC
Permalink
Post by A. McKenney
I'm getting a warning message from a compiler for
a construct that I thought was required by the standard.
class XXX { public: static const int DefaultX = 1; }; //
declaration of XXX::DefaultX
const int XXX::DefaultX; // definition of XXX::DefaultX
With VC++ 2010, this results in a multiply-defined
warning message for XXX::DefaultX.
If I comment out the definition (in A.cpp),
everything compiles fine & without errors.
(The Solaris 10 compiler is happy either way.)
My understanding of the standard was
that the definition is required.
Am I wrong? Or is VC++ wrong?
In the include file, declare it:
static const int DefaultX; // Do not include its value here

In the cpp file, define it:
const int XXX::DefaultX = 1;
--
Fred K


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Francis Glassborow
2011-06-14 19:54:30 UTC
Permalink
Post by Fred
Post by A. McKenney
I'm getting a warning message from a compiler for
a construct that I thought was required by the standard.
class XXX { public: static const int DefaultX = 1; }; //
declaration of XXX::DefaultX
const int XXX::DefaultX; // definition of XXX::DefaultX
With VC++ 2010, this results in a multiply-defined
warning message for XXX::DefaultX.
If I comment out the definition (in A.cpp),
everything compiles fine& without errors.
(The Solaris 10 compiler is happy either way.)
My understanding of the standard was
that the definition is required.
Am I wrong? Or is VC++ wrong?
static const int DefaultX; // Do not include its value here
const int XXX::DefaultX = 1;
Yes, but that completely misses the point. In class initialisation is to
allow the use of the value even when the definition is not visible.
Without that we have to resort to hacks such as using an enum to make
the value visible wherever the class definition is visible.

Typical of the problem is where you want a fixed size array as a
data-member.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Daniel Krügler
2011-06-14 19:52:09 UTC
Permalink
[..]
Post by Fred
static const int DefaultX; // Do not include its value here
const int XXX::DefaultX = 1;
But this has not the same effects as the code from the OP. If written in
your recommended form, you cannot use XXX::DefaultX within the header as
part of a constant expression. But exactly this is the main reason for
the form, where the constant value is provided within the in-class
declaration.

Greetings from Bremen,

Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
SG
2011-06-13 22:44:32 UTC
Permalink
Post by A. McKenney
I'm getting a warning message from a compiler for
a construct that I thought was required by the standard.
class XXX { public: static const int DefaultX = 1; };
const int XXX::DefaultX;
With VC++ 2010, this results in a multiply-defined
warning message for XXX::DefaultX.
[...]
Am I wrong? Or is VC++ wrong?
VC++ is wrong to complain about any multiple definition error because
you only have exactly one definition of XXX:DefaultX. Within a class
definition, the presence of an initializer for a static const integral
member does NOT turn the declaration into a definition.

But you are allowed to omit the definition in this case as long as you
don't take the address of XXX::DefaultX either explicitly or
implicitly (via a const ref binding).

Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Loading...