Topic: VC7 disallowing definition of static const member for integral type: is this permitted by the standard?


Author: tomtitchener@verizon.net ("Tom Titchener")
Date: Wed, 12 Jan 2005 19:15:29 GMT
Raw View
When I compile and link the code below on VC7 (.net) I get the error:

MyClass.obj : error LNK2005: "private: static int const MyClass::num"
(?num@MyClass@@0HB) already defined in Test Compiler.obj

If I comment-out the member definition, everything links and runs Ok.

Does anybody know if the C++ standard says you *cannot* include a definition
for static const members?  Or is this just a (very) minor quibble with VC7?

-------------------------------------------------------------------------------

// MyClass.h - test initialization of static const member variable

class MyClass

{

static const int num = 100;

public:

int GetNum() { return num; }

};

-------------------------------------------------------------------------------

// MyClass.cpp - test initialization of static const member variable

#include "stdafx.h"

#include "MyClass.h"

const int MyClass::num // <-- comment this out to link on VC7 !!

-------------------------------------------------------------------------------

// Test Compiler.cpp test initialization of static const member variable

#include "stdafx.h"

#include "MyClass.h"

using namespace std;

int main()

{

MyClass m;

cout << "m.num " << m.GetNum() << endl;

return 0;

}

-------------------------------------------------------------------------------

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alfps@start.no (Alf P. Steinbach)
Date: Thu, 13 Jan 2005 04:53:27 GMT
Raw View
* "Tom Titchener":
>
> When I compile and link the code below on VC7 (.net) I get the error:
>
> MyClass.obj : error LNK2005: "private: static int const MyClass::num"
> (?num@MyClass@@0HB) already defined in Test Compiler.obj
>
> If I comment-out the member definition, everything links and runs Ok.
>
> Does anybody know if the C++ standard says you *cannot* include a definition
> for static const members?  Or is this just a (very) minor quibble with VC7?

As Ron Natalie has noted, you cannot have multiple definitions.

But there is another issue here, and that's what's constitutes a multiple
definition.

For functions you can use "inline" to fold multiple source level definitions
into one.

For static data items you cannot do that, and that seems rather arbitrary;
and furthermore a static data item defined (i.e. initialized) in a class
definition is therefore not regarded as "inline" as defined member functions
are; it's nearly an inconsistency, and at the very least counter-intuitive.

After all, the compiler has to deal with that issue anyway, folding of static
data item definitions, because for static data items you can have multiple
source level definitions folded simply by using the template mechanism.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "msalters" <Michiel.Salters@logicacmg.com>
Date: Thu, 13 Jan 2005 11:38:56 CST
Raw View
Ron Natalie wrote:
> Tom Titchener wrote:
> > When I compile and link the code below on VC7 (.net) I get the
error:
> >
> > MyClass.obj : error LNK2005: "private: static int const
MyClass::num"
> > (?num@MyClass@@0HB) already defined in Test Compiler.obj
> >
> > If I comment-out the member definition, everything links and runs
Ok.
> >
> > Does anybody know if the C++ standard says you *cannot* include a
definition
> > for static const members?  Or is this just a (very) minor quibble
with VC7?
>
> You can't have multiple definitions in C++, VC7 is certainly within
its
> rights to complain.

Despite the wording of the original author, or the misleading error
message, the code has only one definition. The declararion in the
class has an initializer as per 9.4.2/4

"If a static data member is of const integral or const enumeration
type,
its declaration in the class definition can specify a constant
initializer
which shall be an integral constant expression (5.19). In that case,
the
member can appear in integral constant expressions within its scope.
The
member shall still be defined in a namespace scope if it is used in
the
program and the namespace scope definition shall not contain an
initializer."

Obviously, this is precisely what happens. There is exactly one TU
that has a definition of const int MyClass::num, it is at namespace
scope and it does not have an initializer. VC7 is wrong.
HTH,
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "dtmoore" <dtmoore@rijnh.nl>
Date: Thu, 13 Jan 2005 11:38:56 CST
Raw View
The point you are missing is that in-class initialization for *const*
static data members of integral type implicitly provides a definition.
The compiler makes sure that this implicit definition is only created
once, no matter how many translation units the class declaration
appears in.  Thus the second definition you supplied in the .cpp file
is unnecessary and causes the link-error.

Note that in-class initialization for data members of non-const
integral type, or any flavor of aggregate type (const or not), is
explicitly forbidden by the Standard.

HTH,

Dave Moore

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tomtitchener@verizon.net ("Tom Titchener")
Date: Fri, 14 Jan 2005 01:57:23 GMT
Raw View
I agree it seems like a problem with VC7, especially as Scott Meyers tells
me the code in the sample compiles and links successfully with g++ 3.2 and
Comeau 4.3.3.

Thanks,

Tom Titchener

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dtmoore@email.unc.edu ("Dave Moore")
Date: Fri, 14 Jan 2005 16:04:58 GMT
Raw View
"James Dennett" <jdennett@acm.org> wrote in message
news:I%FFd.109$ru.88@fed1read07...
> dtmoore wrote:
> > The point you are missing is that in-class initialization for *const*
> > static data members of integral type implicitly provides a definition.
>
> But that might safely be "missed", as it is not true -- but maybe I'm
> wrong, in which case I'd be satisfied with a standards reference.
>
Hmm .. it seems from other posts in this thread that perhaps the standard
does not in fact specify the behavior I described. However, that *is* how
specific compilers behave .. I only have access to g++ 3.3 and 3.4, and both
of them compile and link the OP's code both with and without the explicit
definition of num in the .cpp file.  I guess the means I was putting the
cart before the horse ... I guess these compilers supply their own
definition when it is not supplied by the user, and this is *allowed* but
not *required* by the Standard.

> > The compiler makes sure that this implicit definition is only created
> > once, no matter how many translation units the class declaration
> > appears in.  Thus the second definition you supplied in the .cpp file
> > is unnecessary and causes the link-error.
>
> If the object's identity is needed, an explicit definition is required.
> (If only its value is used, we can argue that no definition is needed.)

Ok, so maybe your latter point explains why the OP's example works in modern
compilers, even without the explicit definition in the .cpp file.  (It also
explains the prohibition against in-class initialization of static const
members of aggregate type.)  OTOH, it does not seem that omitting the
definition .

Anyway, thanks for the heads-up.

Dave Moore


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "msalters" <Michiel.Salters@logicacmg.com>
Date: Fri, 14 Jan 2005 10:05:27 CST
Raw View
Alberto Barbati wrote:
..
>    9.4.2/4 says
>
> "If a static data member is of const integral or const enumeration
type,
> its declaration in the class definition can specify a
> constant-initializer which shall be an integral constant expression
> (5.19). In that case, the member can appear in integral constant
> expressions. The member shall still be defined in a namespace scope
if
> it is used in the program and the namespace scope definition shall
not
> contain an initializer."
>
> ... the "shall still be defined" strikes me, because I never
> defined at namespace scope my initialized static const data members
and
> no compiler has ever complained... Just think about all those
> BOOST_STATIC_CONSTANT out there! Where's the catch? Is "appearing in
an
> integral constant expression" not considered to be a "use"?

It will not be anymore ;)
Technically, you are right. The compilers could have complained, but
they didn't have to (no diagnostic req'd). However, since it was
observed that this definition is rather useless in the real world,
it has been proposed to relax the rules in the next standard.
The definition of "used in the program" will probably exclude
contexts in which the compiler should have made a compile-time
substitution.

However, there's one small detail...someone should come up with
the correct words. See Core issue 454, it's in draft.
Regards,
Michiel Salters


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]