template and disambiguation

X

Xenos

The new version of GCC is out and in its list of changes, it talks about the
C++ Standard's requirements for using the typename and template keywords to
disambiguate dependent names. I'm use to seeing typename being used, but
I've never seen template used for this purpose. I've studied there example
for a long time, and still don't understand what situations call for the
template keyword (and reading the standard, to me, is Greek). Can some
explain this. The GCC example follows:


You must now use the typename and template keywords to disambiguate
dependent names, as required by the C++ standard.
struct K {
typedef int mytype_t;
};

template <class T1> struct A {
template <class T2> struct B {
void callme(void);
};

template <int N> void bar(void)
{
// Use 'typename' to tell the parser that T1::mytype_t names
// a type. This is needed because the name is dependent (in
// this case, on template parameter T1).
typename T1::mytype_t x;
x = 0;
}
};

template <class T> void template_func(void)
{
// Use 'template' to prefix member templates within
// dependent types (a has type A<T>, which depends on
// the template parameter T).
A<T> a;
a.template bar<0>();

// Use 'template' to tell the parser that B is a nested
// template class (dependent on template parameter T), and
// 'typename' because the whole A<T>::B<int> is
// the name of a type (again, dependent).
typename A<T>::template B<int> b;
b.callme();
}

void non_template_func(void)
{
// Outside of any template class or function, no names can be
// dependent, so the use of the keyword 'typename' and 'template'
// is not needed (and actually forbidden).
A<K> a;
a.bar<0>();
A<K>::B<float> b;
b.callme();
}
 
D

Denis Remezov

Xenos said:
The new version of GCC is out and in its list of changes, it talks about the
C++ Standard's requirements for using the typename and template keywords to
disambiguate dependent names. I'm use to seeing typename being used, but
I've never seen template used for this purpose. I've studied there example
for a long time, and still don't understand what situations call for the
template keyword (and reading the standard, to me, is Greek). Can some
explain this. The GCC example follows:

You must now use the typename and template keywords to disambiguate
dependent names, as required by the C++ standard.

template <class T> void template_func(void)
{
// Use 'template' to prefix member templates within
// dependent types (a has type A<T>, which depends on
// the template parameter T).
A<T> a;
a.template bar<0>();

// Use 'template' to tell the parser that B is a nested
// template class (dependent on template parameter T), and
// 'typename' because the whole A<T>::B<int> is
// the name of a type (again, dependent).
typename A<T>::template B<int> b;
b.callme();
}

void non_template_func(void)
{
// Outside of any template class or function, no names can be
// dependent, so the use of the keyword 'typename' and 'template'
// is not needed (and actually forbidden).
A<K> a;
a.bar<0>();
A<K>::B<float> b;
b.callme();
}

To paraphrase it again:
You have to use the template construct when you have things like the following:

dependent_name::template nested_template_id
dependent_name.template nested_template_id
dependent_name->template nested_template_id

where
dependent_name is the name of a class template that depends on a
template parameter. In the snippet above, in template_func(void),
A<T> and a are dependent names.

nested_template_id is a function template or class template name,
B<int>, B<T1>, f<int>(), f<T1>().

Why you need it? If you don't give it, the compiler will treat the "<"
in nested_template_id as a less_than operator. It will not attempt to find
out that B or f are actually templates; the compiler's default behaviour is
to assume they are not. AFAIK, the reason for that is that B or f can be
declared and defined in any particular specialization of the class corresponding
to the dependent_name, not necessarily in the "original" template definition.
What is more, a specialization can redefine them altogether, e.g. make them
non-templates.

The key point here is the "dependent_name". A compiler, generally,
cannot assume it knows the nested definitions of a dependent name.

On the other hand, in the last example above (non_template_func(void)), A<K> and
a are not dependent names. The compiler now deals with a specialization
and, therefore, it knows that B and bar are template ids. Thus, conceptually,
there is no need to give it a "template" hint in this case (the current standard
would not allow it anyway (again AFAIK), but there are opinions that it should,
for symmetry).

Denis
 
D

Dave Moore

Xenos said:
The new version of GCC is out and in its list of changes, it talks about the
C++ Standard's requirements for using the typename and template keywords to
disambiguate dependent names. I'm use to seeing typename being used, but
I've never seen template used for this purpose. I've studied there example
for a long time, and still don't understand what situations call for the
template keyword (and reading the standard, to me, is Greek). Can some
explain this. The GCC example follows:

Without going into too much detail or quoting directly from the
standard, I think there are a few clarifications that might help you.

1) the template and typename keywords are only need inside
declarations and definitions of other templated types.

2) Typename is needed because the compiler cannot know when a type
parameter of a template is used as a identifier (e.g. T::A ), whether
it is referring to a type name, or being used for scope resolution.
Thus the typename keyword is required in the case when T::A refers to
a type; in all other cases it is assumed to be for scope-resolution.

3) The template keyword is needed for more complicated declarations
when a template parameter
a) is itself a template, e.g. consider the following declarations:
template <class T, class U> class A {
U<T> u; // error: U is not a template type

template <class T, template <class> U > class B {
U<T> u; // this is now ok
};
the second version explicitly informs the compiler that class U
is allowed to be used as a template type within template class B.

b) has a templated member (function or class) ... the examples
from the GCC page pertain to this case.

In both cases, the compiler would otherwise have no way of knowing
that the attempt to use a template parameter (or member of a template
parameter) as a template was valid.

Hopefully you can now understand the GCC examples you posted a little
better.

Dave Moore
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top