Re: types of classes in template classes
lobequadrat@googlemail.com wrote:
On Apr 26, 11:42 am, Gianni Mariani <gi3nos...@mariani.ws> wrote:
lobequad...@googlemail.com wrote:
On Apr 25, 10:34 am, Gianni Mariani <gi3nos...@mariani.ws> wrote:
...
The code compiled without an error with g++ 2.95.3 ... but not with a
current (see above) compiler ... ?
g++ 2.95.3 was buggy with templates. I wouldn't count on anything that
it accepted being valid.
Ah ... ok - good to know ...
Actually, g++ 2.95.3 was very good with templates. The only
problem is that it is old; it implements templates as they were
defined when it appeared, and not as they are defined today.
Are either of these what you want ?
template <class T> class Test {
public:
class ELEM;
class CONST_ITERATOR {
const typename Test<T>::ELEM * elem;
// note the "typename" keyword
};
class ELEM {
// whatever ...
};
};
[...]
Yepp - the first code snipped solved it ... as far as I understand c++
interprets this statement
"const typename Test<T>::ELEM * elem;" per default as a function and
"typename" changes this, that it is interpreted as a declaration?
The change is that orginally, all names in a template were bound
at the point of instantiation. At that point, the compiler
knows exactly what the name will be, and can treat it
appropriately. The language was changed so that a compiler can
parse and detect many errors in a template when the template is
defined, before any instantiation. This causes two changes in
code:
-- Names in templates are divided into dependent and
non-dependent names. Non-dependent names are completely
bound at the site of the template definition, and are not
looked up again at the site of instantiation. This
typically affects functions which the template author
expects to resolve to a function in a dependent base
class---given something like:
template< typename Toto >
class C : public Toto
{
public:
void f()
{
g() ; // should resolve to Toto::g()...
}
} ;
Because there is nothing in the above code to let the
compiler know that g() is dependent, the compiler tries to
resolve it at the definition site, doesn't find a g(), and
complains (or finds a g(), and that is the function which
will be called, and not the one in the base class). Writing
the call this->g() forces the compiler to consider the name
dependent, and defers resolution until instantiation.
-- It is, regretfully, impossible to correctly parse C++
without knowing which names name types, and which don't.
The same thing holds for templates. For non-dependent
names, this is no problem; the compiler knows what they name
at the definition site. For dependent names, however, it is
a problem, since this information isn't available until
later. The decision taken is that a dependent name will be
assumed to be neither a type nor a template unless you tell
the compiler otherwise. In your code, for example, the
compiler originally assumed that ELEM in Test<T>::ELEM (a
dependent name, since it obviously depends on Test<T>, which
depends on T) is not a type nor a template. Except that in
this case, the declaration is illegal if it isn't. By
adding the keyword typename, you tell the compiler that it
is a type name. Similar situations can occur (albeit much
more rarely) with templates: if the orginal programmer of C,
above, expected g to be a template function, and wrote:
this->g<int>() ;
the compiler would assume at the definition site that the <
was the less than token, which would result in an error. In
such cases, you have to write:
this->template g<int>() ;
so the compiler knows that g will name a template, and that
the < starts the argument list.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34