By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,260 Members | 1,370 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,260 IT Pros & Developers. It's quick & easy.

Is this a bug of the C++ compiler of VS 2005?

P: n/a
See an example at first:

hdr.h
--------------

struct X
{
static const int m = 9;
};

=====================

source1.cpp
---------------

#include "hdr.h"

const int X::m;

=====================

main.cpp
---------------

#include "hdr.h"

int main()
{}

=====================

link error:
source1.obj : error LNK2005: "public: static int const X::m" (?
m@X@@2HB) already defined in main.obj
According to the C++ standard 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. 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."

Judging from the rule above, my code is correct. However, if I
commented the statement: const int X::m; then everything is ok. Why?

Jun 6 '07 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Lighter wrote:
See an example at first:

hdr.h
--------------

struct X
{
static const int m = 9;
};

=====================

source1.cpp
---------------

#include "hdr.h"

const int X::m;

=====================

main.cpp
---------------

#include "hdr.h"

int main()
{}

=====================

link error:
source1.obj : error LNK2005: "public: static int const X::m" (?
m@X@@2HB) already defined in main.obj
According to the C++ standard 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. 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."

Judging from the rule above, my code is correct. However, if I
commented the statement: const int X::m; then everything is ok. Why?
Looks like a defect in their linker. Post to the VC++ newsgroup and/or
submit a bug report to Microsoft.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 6 '07 #2

P: n/a
This is standard C++ behavior.

Just remove the "= 9" from your struct definition and it will work the
way you would expect.
On Jun 6, 9:47 am, Lighter <cqu...@gmail.comwrote:
See an example at first:

hdr.h
--------------

struct X
{
static const int m = 9;

};

=====================

source1.cpp
---------------

#include "hdr.h"

const int X::m;

=====================

main.cpp
---------------

#include "hdr.h"

int main()
{}

=====================

link error:
source1.obj : error LNK2005: "public: static int const X::m" (?
m@X@@2HB) already defined in main.obj

According to the C++ standard 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. 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."

Judging from the rule above, my code is correct. However, if I
commented the statement: const int X::m; then everything is ok. Why?

Jun 6 '07 #3

P: n/a
witkamp wrote:
This is standard C++ behavior.

Just remove the "= 9" from your struct definition and it will work the
way you would expect.
lol. Of course, removing a piece the program solves the problem :)

But have you read the message? Why should him remove =9 if he wants his
const static int member to be initialized in the class definition?
He also cited the standard, so, if you do not agree with something,
please provide an explanation.

Regards,

Zeppe
Jun 6 '07 #4

P: n/a
On Wed, 6 Jun 2007 13:13:07 -0400, Victor Bazarov wrote:
>Looks like a defect in their linker. Post to the VC++ newsgroup and/or
submit a bug report to Microsoft.
I don't know if it has ever been reported but it is an old bug, dating
back at least to VC 7.1. It is affected by the /Za flag, BTW: usually
/Za will make everything link, but then the resulting exe might not
work at all (great, isn't it? 98% conformity). This happens for
instance in the unit tests for
<http://breeze.svn.sourceforge.net/viewvc/breeze/trunk/breeze/meta/maximum.hpp>

but also in much simpler cases.

--
Gennaro Prota -- C++ Developer, For Hire
https://sourceforge.net/projects/breeze/
(replace 'address' with 'name.surname' to mail)
Jun 6 '07 #5

P: n/a
Visual C++ is not an iso-compliant compiler ...
(no matter which version)
Jun 7 '07 #6

P: n/a
Sascha Bohnenkamp wrote:
Visual C++ is not an iso-compliant compiler ...
(no matter which version)
None of the current compilers is an iso-compliant compiler. Visual C++
is a good compiler, if you have some specific issue we can discuss them,
like in the OP post, but please, refrain from trolling.

Regards,

Zeppe

Jun 7 '07 #7

P: n/a
On 6 kesä, 19:47, Lighter <cqu...@gmail.comwrote:
However, if I
commented the statement: const int X::m; then everything is ok. Why?
Because m is defined in the struct already. You don't need
another definition.

Jun 7 '07 #8

P: n/a
Krice wrote:
On 6 kesä, 19:47, Lighter <cqu...@gmail.comwrote:
>However, if I
commented the statement: const int X::m; then everything is ok. Why?

Because m is defined in the struct already. You don't need
another definition.
c'mon guys. Let's read the messages before answering ;)

Regards,

Zeppe
Jun 7 '07 #9

P: n/a
Krice wrote:
: On 6 kesä, 19:47, Lighter <cqu...@gmail.comwrote:
:: However, if I
:: commented the statement: const int X::m; then everything is ok.
:: Why?
:
: Because m is defined in the struct already. You don't need
: another definition.

You do actually, but sometimes you get away with it.

Try passing the value by const reference, like to std::max(), and the
linker will now complain that it cannot find the definition.
Bo Persson
Jun 7 '07 #10

P: n/a
On 7 Jun, 11:49, Krice <pau...@mbnet.fiwrote:
On 6 kesä, 19:47, Lighter <cqu...@gmail.comwrote:
However, if I
commented the statement: const int X::m; then everything is ok. Why?

Because m is defined in the struct already.
No it's not. It's declared and given an initialiser.
You don't need
another definition.
The OP's code doesn't have "another" definition, it has exactly one
definition.

Reread the section of the standard that the OP quoted.

Gavin Deane

Jun 7 '07 #11

P: n/a
On Jun 6, 2:23 pm, witkamp <theodore.witk...@gmail.comwrote:
This is standard C++ behavior.
No, it is not. As quoted by the colleague, the Standard allows the
initialization inside the class declaration, but one still needs to
define the variable outside. What the Visual Studio does is to allow
the declaration without definition, defining it automatically. When
one defines the same variable, the VS "help" ends messing up the code.

You're right, Lighter, the VS behavior is error prone regard to the
Standard Spec.

Wanderley Caloni
======================
http://www.cthings.org

Jun 8 '07 #12

P: n/a
ppl
On Jun 6, 1:47 pm, Lighter <cqu...@gmail.comwrote:
See an example at first:

hdr.h
--------------

struct X
{
staticconstint m = 9;

};

=====================

source1.cpp
---------------

#include "hdr.h"

constint X::m;

=====================

main.cpp
---------------

#include "hdr.h"

int main()
{}

=====================

linkerror:
source1.obj : error LNK2005: "public:staticintconstX::m" (?
m@X@@2HB) already defined in main.obj

According to the C++ standard 9.4.2/4
"If astaticdata member is ofconstintegralorconstenumeration
type, its
declaration in the class definition can specify a constant-initializer
which
shall be anintegralconstant expression. In that case, the member
can
appear inintegralconstant 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."

Judging from the rule above, my code is correct. However, if I
commented the statement:constint X::m; then everything is ok. Why?
I did observe the same problem in VC++2003 recently. I've read the
same paragraph of the standard and came to the same conclusion.

This problem can become tricky when you are also dealing with g++. The
GNU compiler properly implement the standard (afaik) and will yield a
linking error if you do not properly define m in a translation unit.
However, if you omit m definition, it may not yield a linking error in
some cases where, I assume, m references are inlined.

An example of this is when you use m directly (e.g. X::m) it may be
inlined and may not yield a linking error. Otoh, if you access m
indirectly via a non-inline method, g++ will generate the linking
error if you omit m definition.

See also http://docs.freebsd.org/info/g++FAQ/...a_members.html

We resolved to simply remove the initializer in the declaration and
place it in the definition. This will work with g++ and fix the issue
with VC++2003/2005.

Please inform me if someone already wrote a bug report to Microsoft
and/or know of an acknowledgment of this problem on Microsoft website.

Thank you,
ppl

Jun 16 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.