1, typename keyword
When you declare a template parameter, prefix the keyword class and typename are interchangeable, but can only be used when the internal typename type name using the template parameter T that is nested dependent name.
In the C ++ standardization process, the introduction of keywords typename
to illustrate: internal template type parameter identifier (associated type, common in various STL containers) may also be a type:
such as:
template<typename T>
class MyClass
{
typename T::SubType* ptr;
}
Introduce a few concepts within the template parameter names here;
Slave name (dependent names): name that appears in the template (Template), dependent on a template (Template) parameters, such as T t;
nested dependent name (nested dependent names): dependent name in the form of a nested class, the T :: const_iterator ci;
non-subject name (non-dependent names): name of template does not depend on any parameters, such as the int value; any time referent in a nested dependent type name template (template), it is necessary a previous position add the keyword typename;
If not specifically stated typename, nested slave name, parsing may occur (the parse) ambiguity, may be error (GCC): error: need 'typename' before 'T :: xxx' because 'T' is a dependent scope.
such as:
template<typename T>
class MyClass
{
/*typename*/ T::SubType* ptr;
}
In the above procedure, the second typename is used to illustrate, with the SubType is a type of class defines the interior T, i.e. associated type, therefore, a pointer PTR is pointer type T :: SubType. If you do not use typename, T :: SubType priority will be seen as a static member T, which is a specific and variable or object, so the following expression:
T::SubType* ptr;
At this time, the compiler will not be able to distinguish what is this SubType, because SubType may be a static variable in the template parameter T, ptr can be seen as a global variable, then the code will be seen as the product of the static SubType member of class T and the ptr or it may be a typedef for example SubType
class Class_T{
typedef int SubType;
...
};
The above code is converted into one that is this:
int *x;
2, the use of several nested dependent name of scene typename
a, if the template name appears in the templates is dependent on a parameter, called the slave name (dependent name). If the slave name in the form of a nested class, we called nesting slave name (nested dependent name), for example as follows:
template<typename T>
void print(const T & container)
{
T::const_iterator iter(container.begin());
cout << *iter << endl;
int value = *iter;
return;
}
- In the above code, the ITER type template-dependent parameter T, it is called dependent name;
- Similarly, value type is built into the language type, the template does not depend on any parameters, it is called non-subject name;
- C ++ compiler in the face of a slave name, if this time the slave name and other types of nested, so that at the iter T :: const_iterator type, where T :: const_iterator called a nested dependent type name (nested in T type, belonging to the template parameter T)
or
template<typename T> // typename allowed (as is "class")
void f(const T& container, // typename not allowed typename T::iterator iter); // typename required
Above T is not nested dependent type name (it is not nested within any "depends on a template parameter" thing), so when the container does not need to be declared as a leading typename.
However, T :: iterator is nested dependent type name, as it must typename preamble.
b, when a template class inside typedef types, if this type associated with the template parameter T, you need to use typename. That is the form:
Template < class T>
class the Test
{
public :
typedef Map < int , T> TEMPLATE_MAP; // TEMPLATE_MAP not need typename, because it does not rely on other names
typedef Map < int , T> :: Iterator TEMPLATE_MAP_ITER; // error fitted! sets slave name, independent of other iterator class name
typedef typename Map < int , T> :: iterator TEMPLATE_MAP_ITER; // Yes
};
C, exceptions: nested dependent type name, if the list of base classes (base class list) and a member of the initial value columns (member initialization list) is not used typename;
/*
* BInsertSort.cpp
*
* Created on: 2014.4.17
* Author: Spike
*/
#include <iostream>
#include <vector>
using namespace std;
struct Number {
Number(int x) {
std::cout << "Number = " << x << std::endl;
}
};
template<typename T>
struct Base{
typedef Number Nested;
};
template<typename T>
class Derived: public Base<T>::Nested { // do typename
public :
Explicit the Derived ( int X): Base <T> :: the Nested (X) { // do typename
typename Base <T> :: the Nested TEMP ( . 7 ); // must
}
};
int main () {
the Derived < int > D ( . 5 );
return 0 ;
}