Confused about typename

73 views
Skip to first unread message

Walter Milner

unread,
Apr 13, 2002, 10:19:50 AM4/13/02
to
In Accelerated C++ it is written (8.1.1) that you need to use typename
to precede a template parameter which is a type. This was not totally
clear to me, so I wrote a little prog:

#include <iostream>

struct intIDRecord
{
typedef int IDType;
IDType ID;
int data;
};

struct doubleIDRecord
{
typedef double IDType;
IDType ID;
int data;

};

template <class T>
void displayID(T x)
{
typedef typename T::IDType idt;
idt y =x.ID;
std::cout << y << "\n";
}

int main( void )
{

intIDRecord s1;
s1.ID=99;
displayID(s1);

doubleIDRecord s2;
s2.ID=0.384;
displayID(s2);
return 0;
}

This worked fine and I thought I understood. Then I deleted typename
so in the template I just have
typedef T::IDType idt;
and it still worked. This prompted more thought - even though the
compiler cant tell in the template definition whether T::IDType is a
type, it can when it instantiates it with either intIDRecord or
doubleIDRecord (or anything else). And in that case, why does it need
typename? This in Metrowerks Codewarrior IDE v4.1. TIA

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

domi

unread,
Apr 13, 2002, 4:10:26 PM4/13/02
to
Walter Milner wrote:

>
> template <class T>
> void displayID(T x)
> {
> typedef typename T::IDType idt;
> idt y =x.ID;
> std::cout << y << "\n";
> }

what they mean is that you should write
template <typename T>
void displayID(T x)
{
};

so you can use the function too for int's.
if you write class, you shouldn't be allowed to use the function on int's,
since an int is _not_ a class
domi

Stephen Clamage

unread,
Apr 13, 2002, 4:52:47 PM4/13/02
to
On 13 Apr 2002 10:19:50 -0400, walter...@hotmail.com (Walter
Milner) wrote:

>In Accelerated C++ it is written (8.1.1) that you need to use typename
>to precede a template parameter which is a type.

>[ ... example deleted ... ]


>
>This worked fine and I thought I understood. Then I deleted typename
>so in the template I just have
>typedef T::IDType idt;
>and it still worked. This prompted more thought - even though the
>compiler cant tell in the template definition whether T::IDType is a
>type, it can when it instantiates it with either intIDRecord or
>doubleIDRecord (or anything else). And in that case, why does it need
>typename?

You need typename to tell the compiler that an identifier that depends
on a template parameter is a type. Otherwise, the compiler is supposed
to assume it is NOT the name of a type.

The reason for the rule is to allow detection of some kinds of errors
in the template definition itself, instead of waiting until
instantiation time and reporting the same error in every instantiation
of the template. At a minimum, the compiler needs to know which names
are types even to begin parsing a declaration. Example:

template<class U> void f(U u) { U::A * B = 0; ... }

If A is the name of a type, the first statement of f declares B to be
a pointer to that type, initialized to null. Any usage of B in f that
is not consistent with B as a pointer to a type can be diagnosed as an
error.

But A might be an object of type T, in which case the "*" is a
multiply operator. The B must refer to some B object in an outer
scope, or else the code is invalid. If B is a visible object, the
statement might be a syntax error, but it also might be legal. Suppose
we had already seen
T B; // B is also of type T
int& operator*(const T&, const T&);
The first statement of f is valid if f is instantiated on type T,
and possibly on some other types as well.

With the "typename" rule, U::A is not a type, and if no overloaed
operator* is visible, the template declaration cannot be valid, and
the compiler can report it as an error. If you add "typename" to U::A,
the compiler knows A is a type, and can possibly diagnose other errors
in the template definition.

Most compilers already handled templates under the older rule, before
typename was introduced. Taking advantage of the newer rule would
require rewriting the template processing, which most compiler vendors
did not want to do, at least not yet. They have been busy enough with
other completeness and correctness issues. Some compilers diagnose the
missing "typename", but many of them just make it a warning, if only
to allow older code to compile.
---
Steve Clamage, stephen...@sun.com

Edward Diener

unread,
Apr 14, 2002, 11:42:22 AM4/14/02
to
"domi" <fritme...@pandora.be@telenet-ops.be> wrote in message
news:bSYt8.15468$Ze....@afrodite.telenet-ops.be...

> Walter Milner wrote:
>
> >
> > template <class T>
> > void displayID(T x)
> > {
> > typedef typename T::IDType idt;
> > idt y =x.ID;
> > std::cout << y << "\n";
> > }
>
> what they mean is that you should write
> template <typename T>
> void displayID(T x)
> {
> };
>
> so you can use the function too for int's.
> if you write class, you shouldn't be allowed to use the function on int's,
> since an int is _not_ a class

That is simply not true. In the case of the template parameter list for
class templates or function templates, either "typename" or "class" can be
used interchangeably with equal effect whether or not the actual type is a
class or not. It is just syntactical sugar which word you use in the case
you mention.

In the case given in the original example, "typedef typename T::IDType
idt;", only "typename" is correct.

Robert W Hand

unread,
Apr 14, 2002, 11:49:33 AM4/14/02
to
On 13 Apr 2002 16:10:26 -0400, domi

<fritme...@pandora.be@telenet-ops.be> wrote:
>
>>
>> template <class T>
>> void displayID(T x)

>


>what they mean is that you should write
>template <typename T>
>void displayID(T x)

>if you write class, you shouldn't be allowed to use the function on int's,

>since an int is _not_ a class

In this context the use of class is equivalent to the use of typename,
i.e. the term class in a template parameter can be used for any type
including int. See subclause 14.2/1.

Best wishes,

Bob

Sebastian Kapfer

unread,
Apr 14, 2002, 8:01:38 PM4/14/02
to
On Sat, 13 Apr 2002 22:10:26 +0200, domi wrote:

> Walter Milner wrote:
>
>> template <class T>
>> void displayID(T x)
>> {
>> typedef typename T::IDType idt;
>> idt y =x.ID;
>> std::cout << y << "\n";
>> }
>
> what they mean is that you should write template <typename T> void
> displayID(T x)
> {
> };
>
> so you can use the function too for int's. if you write class, you
> shouldn't be allowed to use the function on int's, since an int is _not_
> a class

"class" and "typename" are exactly equivalent in a template argument list.
Even though "int" is not a class, it can be used with the code provided by
the OP.

Reply all
Reply to author
Forward
0 new messages