[Release b] <t4m_bug_nonexpstat> Sat May 15 17:14:51 WEST 2004 In the current release of tendra4minix (a), after fixing <t4m_bug_nonexport>, the compilation of the file nonexpstat.C produces this error "nonexpstat.C", line 17: Error: [ISO 14]: The non-exported template 'Hola < Hola < double > >::hola' has not been defined. This is the error ERR_temp_decl_undef, and it is being reported in the function copy_template [instance.c]. The program nonexpstat_p.C contains a partial specialization. Although it is not the same, it is reassuring to know that it works, and that both static members get initialized correctly. The program nonexpstat_e.C is compiled without problems; it uses an asignment (i. e., the copy constructor) to initialize the static member through a temporary object which is built by an explicit call to the default constructor. Well, this is not a bug. The explicit specialization template <> Hola<double> Hola< Hola<double> >::hola; is a declaration (in spite of having the same syntax as a default initialization). The spec X3J16/96-0225 WG21/N1043, section '14.7.3 Explicit specialization' [temp.expl.spec], paragraph 14, reads 14An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization. template<> X Q<int>::x; This is a declaration regardless of whether X can be default initial- ized (_dcl.init_). ] Anyway, it is illustrative to know which functions are involved in this declaration. The function that processes the declaration is make_object_decl [declare.c], called directly from the parser; make_object_decl calls bind_specialise [instance.c] to know if the declaration is an explicit instantiation [bound_specialise = 2], an explicit specialization [bound_specialise = 1], or something else [bound_specialise = 0], for example, a partial specialization or a declaration of a new template. Below, the conditional if ( tag == type_templ_tag && bound_specialise ) { /* A template specialisation is a declaration (probably) */ df = dspec_none ; } else { /* Everything else is a definition */ df = dspec_defn ; } decides that it is a declaration (according to the spec). If we wanted to force the compiler to consider it a default initialization, we could make the assignment 'df = dspec_defn' instead of 'df = dspec_none' (I have tested this hack with nonexpstat.C and it works). The function init_object [initialise.c] is in charge of initializing the static data member, no matter if the class is a template or not; I think it is called from the parser, but I'm not sure. This function takes two arguments: the identifier to initialize and the initializer (an expression), which is NULL in the case of default initializations. Default initializations are processed by the conditional /* Provide default definition if necessary */ if ( ds & dspec_defn ) { def = 1 ; if ( IS_NULL_exp ( e ) ) { e = init_general ( t, e, id, LANGUAGE_C ) ; if ( !IS_NULL_exp ( e ) && IS_exp_zero ( e ) ) def = 2 ; } } init_general [initialise.c] calls init_empty [initialise.c], and finally init_empty calls init_default [construct.c], which generates the initializer for default-initialized objects. Notes. [ ] Summary of the behaviour of three compilers. Program GCC-2.95.3 TenDRA-4.1.2 Compaq C++ V6.5-040 (Tru64 V5.1B) --------------------------------------------------------------------------- nonexpstat.C Sí/No[1] No/- Sí/No[1] nonexpstat_e.C Sí/No[2] Sí/Sí Sí/No[2] nonexpstat_p.C No/- [3] Sí/Sí No/- [3] The first bit tells whether the program is compiled without errors, and the second whether it is executed correctly. [1] Default constructor not called. [2] Copy constructor not called. [3] Partial specialization rejected.