Strange gcc 3.2.2-5.8 behavior

The following bit of code gives me an undefined symbol (l1) when using gcc 3.2.2-5.8. Is there something wrong with the code or is there a bug in the compiler or a setting I don't know about, etc? struct S { static const short l1 = 10; }; void go(const short& l) {}; // causes undefined symbol l1 int main(int argc, char* argv[]) { go(S::l1); return 0; } If I do normal, non-in-class-initialization, the problem doesn't appear nor does it appear if I accept the short by value in go. Thanks, John

Hi John, From the standard: 9.4.2 Static data members 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. so adding the line const short S::l1; solves the problem. But I still don't understand neither why passing by value doesn't cause the error. On 11 Feb 2005, at 01:03, John Eddy wrote:
The following bit of code gives me an undefined symbol (l1) when using gcc 3.2.2-5.8. Is there something wrong with the code or is there a bug in the compiler or a setting I don't know about, etc?
struct S { static const short l1 = 10; };
void go(const short& l) {}; // causes undefined symbol l1
int main(int argc, char* argv[]) { go(S::l1); return 0; }
If I do normal, non-in-class-initialization, the problem doesn't appear nor does it appear if I accept the short by value in go.
Thanks, John _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Tony Han Bao tonybao@mac.com

On Fri, Feb 11, 2005 at 02:23:42AM +0000, Tony Han Bao wrote:
Hi John,
From the standard:
9.4.2 Static data members
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.
so adding the line
const short S::l1;
solves the problem.
Note this is documented here: http://gcc.gnu.org/onlinedocs/gcc/Static-Definitions.html#Static-Definitions
But I still don't understand neither why passing by value doesn't cause the error.
Because when passing by value S::l1 is only used as an integral constant expression, to initialise a variable. Passing by reference is similar to taking its address, which requires it to *have* and address, which requires if to have storage, so it must have been defined somewhere. jon
On 11 Feb 2005, at 01:03, John Eddy wrote:
The following bit of code gives me an undefined symbol (l1) when using gcc 3.2.2-5.8. Is there something wrong with the code or is there a bug in the compiler or a setting I don't know about, etc?
struct S { static const short l1 = 10; };
void go(const short& l) {}; // causes undefined symbol l1
int main(int argc, char* argv[]) { go(S::l1); return 0; }
If I do normal, non-in-class-initialization, the problem doesn't appear nor does it appear if I accept the short by value in go.
-- "We're doomed!" - C3PO

Thank you Jonathan and Tony, Fortunately, the class in which I am using this construct is templatized so the initializations as you (Tony) suggested are fine appearing just below the class. If it weren't a templatized class, doing so would produce multiply defined symbol errors. I suppose the only way around that is to have an implementation file which requires a library be built, etc. yes? (bummer) Thanks, John Jonathan Wakely wrote:
On Fri, Feb 11, 2005 at 02:23:42AM +0000, Tony Han Bao wrote:
Hi John,
From the standard:
9.4.2 Static data members
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.
so adding the line
const short S::l1;
solves the problem.
Note this is documented here: http://gcc.gnu.org/onlinedocs/gcc/Static-Definitions.html#Static-Definitions
But I still don't understand neither why passing by value doesn't cause the error.
Because when passing by value S::l1 is only used as an integral constant expression, to initialise a variable. Passing by reference is similar to taking its address, which requires it to *have* and address, which requires if to have storage, so it must have been defined somewhere.
jon
On 11 Feb 2005, at 01:03, John Eddy wrote:
The following bit of code gives me an undefined symbol (l1) when using gcc 3.2.2-5.8. Is there something wrong with the code or is there a bug in the compiler or a setting I don't know about, etc?
struct S { static const short l1 = 10; };
void go(const short& l) {}; // causes undefined symbol l1
int main(int argc, char* argv[]) { go(S::l1); return 0; }
If I do normal, non-in-class-initialization, the problem doesn't appear nor does it appear if I accept the short by value in go.

On Fri, Feb 11, 2005 at 11:11:51AM -0500, John Eddy wrote:
Thank you Jonathan and Tony,
Fortunately, the class in which I am using this construct is templatized so the initializations as you (Tony) suggested are fine appearing just below the class. If it weren't a templatized class, doing so would produce multiply defined symbol errors. I suppose the only way around that is to have an implementation file which requires a library be built, etc. yes? (bummer)
That's right. If you couldn't have an implementation file where the member could be defined then you would have to either ensure that you never "use" the member in your program (where "use" doesn't include using it as an integral constant expression, but does include many other useful things, such as taking a reference to it or its address,) or you could replace it with an enumerator: class S { enum { l1 = 23 }; }; An enumerator has no storage, so *can't* be "used" in the program in a way that would cause problems. regards, jon -- "There are perhaps 5% of the population that simply *can't* think. There are another 5% who *can*, and *do*. The remaining 90% *can* think, but *don't*." - R. A. Heinlein

On Fri, Feb 11, 2005 at 04:58:20PM +0000, Jonathan Wakely wrote:
On Fri, Feb 11, 2005 at 11:11:51AM -0500, John Eddy wrote:
Thank you Jonathan and Tony,
Fortunately, the class in which I am using this construct is templatized so the initializations as you (Tony) suggested are fine appearing just below the class. If it weren't a templatized class, doing so would produce multiply defined symbol errors. I suppose the only way around that is to have an implementation file which requires a library be built, etc. yes? (bummer)
Actually - there's at least one other option, don't define the member and require users of the header to add a definition somewhere in their program. That's probably an excellent way of ensuring noone ever uses your header ;) jon -- "I find the Law of Fives to be more and more manifest the harder I look." - Lord Omar Khayyam Ravenhurst

John Eddy wrote:
Thank you Jonathan and Tony,
Fortunately, the class in which I am using this construct is templatized so the initializations as you (Tony) suggested are fine appearing just below the class. If it weren't a templatized class, doing so would produce multiply defined symbol errors. I suppose the only way around that is to have an implementation file which requires a library be built, etc. yes? (bummer)
You can often get around this problem by inheriting the static member from a specialization of a class template. Jonathan
participants (4)
-
John Eddy
-
Jonathan Turkanis
-
Jonathan Wakely
-
Tony Han Bao