SourceForge.net Logo

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