The sample codes¡G ========================================== #include <iostream> #include <vector> struct T { static char const a = 3; }; std::vector<char> ddd; int main() { ddd.push_back(T::a); /* this line of codes trigger the errors */ std::cerr << ddd.front() << std::endl; return 0; } ======================================== gcc-3.0.x 3.2.x 3.3.x 3.4.x compile the above program will produce errors like this: ======================================= /tmp/ccPOPHZ6.o(.text+0x124): In function `main': : undefined reference to `T::a' collect2: ld returned 1 exit status ======================================= However, if I use gcc-2.95, then there will be no errors. If I modify the codes from: ... ddd.push_back(T::a); ... to ... ddd.push_back(static_cast<char>(T::a)); ... then gcc-3.0.x 3.2.x 3.3.x 3.4.x will be fine. Is this a bug in gcc 3.x?
No you need to add the following to your code: const char T::a; Since you don't supply the memory location otherwise (which is required by the standard).
But according the standard, 'const static' data members of an intergral type can now be initialized _inside_ their class. In this case, the initialization is _also_ a definition, so _no_ further definitions are reuquired outside the class body.
#include <vector> struct T { static char const a = 3; }; void fff(char a) { } std::vector<char> b; int main() { fff(T::a); /* this line of codes is fine. */ b.push_back(T::a); /* however, this line of codes is an error. */ return 0; }
(In reply to comment #2) > But according the standard, 'const static' data members of an intergral type can > now be initialized _inside_ their class. In this case, the initialization is > _also_ a definition, so _no_ further definitions are reuquired outside the class > body. No it is not a definition, a definition (or is it the other way around). Still this is invalid. Yes the compiler is allowed to "optimize" the constant which is why it worked in 2.95.3 (well because the defintion of push_back was wrong). Oh, one more thing, the vector code is equivalent to (so you take the address): struct T { static char const a = 3; }; void fff(const char &a){ } int main() { fff(T::a); return 0; }
I understand what you mean. But why the following codes works: #include <iostream> #include <vector> struct T { static char const a = 3; }; std::vector<char> ddd; int main() { ddd.push_back(static_cast<char>(T::a)); // <========= here std::cerr << ddd.front() << std::endl; return 0; } and if I pass an constant to a function which takes its address, then why the folloing codes doesn't produce errors? void fff(char const &a) { } int main() { fff(4); return 0; }
(In reply to comment #5) > I understand what you mean. > But why the following codes works: > > #include <iostream> > #include <vector> > > struct T > { > static char const a = 3; > }; > > std::vector<char> ddd; > > int > main() > { > ddd.push_back(static_cast<char>(T::a)); // <========= here > > std::cerr << ddd.front() << std::endl; > > return 0; > } > > and if I pass an constant to a function which takes its address, Because you changed an lvalue to a rvalue. > then why the folloing codes doesn't produce errors? Because constants are rvalues so there is going to be a temporary variable made for you.
I see. But why compiler doesn't also make a temporary variable for the constant defined in a class scope? Such as following codes: struct T { static int const a = 3; }; void fff(int const &a) { } int main() { fff(T::a); /* compiler will not make a temporary variable for it. */ fff(4); /* compiler will make a temporary variable for it. */ return 0; }
Bacause T::A is a lvalue.
so the "... = 3;" initialization statement below is a definition or a declaration? According to the C++ standard, its a definition. Should the compiler allocate a memory space for it? struct T { static char const a = 3; }; And... If I need to allocate memory spaces for it manually, why the standard explicitly specify this kind of coding style? ======================== struct T { static char const a = 3; /* standard explicity specify that the initialization & definition can be put here. */ }; char const T::a; /* If I need this line of codes, then the initialization above should be a declaration, not a definition. But a declaration can be initialized? */ ======================== struct T { static char const a; }; char const T::a = 3; ========================
Here is the relevant section of the standard (TC1, section 9.4.2, paragraph 4): If a 'static' data member is of 'const' integral or 'const' enumeral 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'.
*** Bug 29219 has been marked as a duplicate of this bug. ***