
Robert Ramey wrote:
David Abrahams wrote:
Rene Rivera <grafik.list@redshift-software.com> writes:
Many of the problems that CodeWarrior, and True64, have with the serialization library stem from the behavior of CW to not call constructors for static data members in one particular class in the library. I've come to think that this is standard conforming behavior.
The serialization library relies on a static member of a template class being constructed at global initialization time to figure out what all the serialized classes are. The problem is that the template class is being instantiated implicitly. Which for most compilers also instantiates any static members of that template class. It's my understanding that this violates 14.7.1.7:
"The implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated."
Question I have.. Is my understanding correct? Or is this a bug in CW part?
Your understanding is certainly correct. It's standard practice in traits templates, for example, to do something like:
template <class T> struct is_whatever { static T& x;
template <class U> char test(U&);
template <class U> char (& test( whatever<U>& ) )[2];
enum { value = sizeof(test(x)) == 2 }; };
Nobody ever even writes an initializer for x.
This is different than our case. we have:
template<class T> struct A { static T t; ... };
template<class T> T A<T>::t
and somewhere in the program we do
void f(){ T & t = A<T>::t; }
To correct that a bit.. In the code in question we actually do the equivalent of: template <typename T> void f() { void * t = &A<T>::t; } Hence the implicit aspect of the instantiation. Which I think CW decides is not sufficient for the semantic requirement that the other rules in 14.7.1 refer to. But it's not clear how the other rules of 14.7.1 should apply for the implicit instantiation case that 14.7.1.7 refers to. -- Well at least not clear to me :-) But 14.7.1.1 does say this... which possibly supports what 14.7.1.7 says. 14.7.1.1: "The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, _but not of the definitions_ or default arguments, of the class member functions, member classes, _static data members_ and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions."
We expect A<T>::t to be instanticiated and the program to link and run as expected. In fact on most compilers it does this. This group includes those known to be the most conforming ones including the latest GCC, VC and Comeau compilers.
With CW, it seems that A<T> t is allocated but the constructor for t isn't being called - at least at pre-compile time. It might be being called on first usage as it would be in the following case.
void f() { static T t; .. }
It's not getting called, no matter what. Or more precisely CW is not adding the constructor+instance to the global initialization function list that CW generates. The only circumstance it generates the init function is one explicitly defines the member: struct B; template A<B>::t;
Now Rene has looked into this and raises the possibility that CW is correct in its behavior - and all the other compilers are wrong. Rene's quote from the standard would suggest to me that A<T>::t should never even be instantiated. If that's the case why is A<T>::t even being allocated?
This is quite murky to me.
Somewhat murky for me also. I think this not an area of compilers that gets exercised this way. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - Grafik/jabber.org