
[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.