Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

The typename keyword

Consider the following:

//: C05:TypenamedID.cpp {-bor}
// Uses 'typename' as a prefix for nested types.
 
template<class T> class X {
// Without typename, you should get an error:
typename T::id i;
public:
void f() { i.g(); }
};
 
class Y {
public:
class id {
public:
void g() {}
};
};
 
int main() {
X<Y> xy;
xy.f();
} ///:~
 

The template definition assumes that the class T that you hand it must have a nested identifier of some kind called id. Yet id could also be a static data member of T, in which case you can perform operations on id directly, but you can t create an object of the type id. In this example, the identifier id is being treated as if it were a nested type inside T. In the case of class Y, id is in fact a nested type, but (without the typename keyword) the compiler can t know that when it s compiling X.

If the compiler has the option of treating an identifier as a type or as something other than a type when it sees an identifier in a template, it will assume that the identifier refers to something other than a type. That is, it will assume that the identifier refers to an object (including variables of primitive types), an enumeration, or something similar. However, it will not cannot just assume that it is a type.

Because the default behavior of the compiler is to assume that a name that fits the above two points is not a type, you must use typename for nested names (except in constructor initializer lists, where it is neither needed nor allowed). In the above example, when the compiler sees typename T::id, it knows (because of the typename keyword) that id refers to a nested type and thus it can create an object of that type.

The short version of the rule is: if a type referred to inside template code is qualified by a template type parameter, you must use the typename keyword as a prefix, unless it appears in a base class specification or initializer list in the same scope (in which case you must not).

The above explains the use of the typename keyword in the program TempTemp4.cpp. Without it, the compiler would assume that the expression Seq<T>::iterator is not a type, but we were using it to define the return type of the begin( ) and end( ) member functions.

The following example, which defines a function template that can print any Standard C++ sequence, shows a similar use of typename:

//: C05:PrintSeq.cpp {-msc}{-mwcc}
// A print function for Standard C++ sequences.
#include <iostream>
#include <list>
#include <memory>
#include <vector>
using namespace std;
 
template<class T, template<class U, class = allocator<U> >
class Seq>
void printSeq(Seq<T>& seq) {
for(typename Seq<T>::iterator b = seq.begin();
b != seq.end();)
cout << *b++ << endl;
}
 
int main() {
// Process a vector
vector<int> v;
v.push_back(1);
v.push_back(2);
printSeq(v);
// Process a list
list<int> lst;
lst.push_back(3);
lst.push_back(4);
printSeq(lst);
} ///:~
 

Once again, without the typename keyword the compiler will interpret iterator as a static data member of Seq<T>, which is a syntax error, since a type is required.

Typedefing a typename

It s important not to assume that the typename keyword creates a new type name. It doesn t. Its purpose is to inform the compiler that the qualified identifier is to be interpreted as a type. A line that reads:

typename Seq<T>::iterator It;
 

causes a variable named It to be declared of type Seq<T>::iterator. If you mean to create a new type name, you should use typedef, as usual, as in:

typedef typename Seq<It>::iterator It;
 

Using typename instead of class

Another role of the typename keyword is to provide you the option of using typename instead of class in the template argument list of a template definition:

//: C05:UsingTypename.cpp
// Using 'typename' in the template argument list.
 
template<typename T> class X {};
 
int main() {
X<int> x;
} ///:~
 

To some, this produces clearer code.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire