In C + + templates, you can use class or typename to declare template parameters, so what's the difference between these two keywords?
Template parameter declaration
for template parameter declarations, there is no difference between the two parameters, meaning the same.
template class simple;
template class Simple;
The above two lines are declared a template class simple.
Indicates type
If we have such a piece of code:
Template
void Add (const t &acontainer, T &sum)
{
T::const_iterator iter = Container.begin ();
for (; Iter!= container.end (); ++iter) {
sum = *iter;
}
}
ITER type is t::const_iterator, this type relies on template parameter T. The name of the dependent template parameter is called the dependency name. When this dependency name is again in a class, it is called a nested dependency name. Relative, called a non-nested dependency name.
Nested dependency names can cause compiler compilation difficulties, such as the following code:
Template
void Add (const T &container)
{
t::const_iterator *x;
...
}
This looks like declaring a variable x, which is of type T::const_iterator *. But the compiler does not know that it is possible to have another static data member in class T const_iterator, or just have a global variable x. The code above then becomes a multiplication operation. This is because the C + + compiler will temporarily shelve the data type that needs to be inferred when it processes the template, and then determine it at run time.
When the compiler encounters a nested dependency name in a template, the compiler treats it as a variable. Therefore, you need to show the compiler, which requires the use of Keyword typename.
Template
void Add (const t &container, T &sum)
{
typename T::const_iterator iter = Container.begin () ;
for (; Iter!= container.end (); ++iter) {
sum = *iter;
}
}
Therefore, when you use a nested dependency type name, you need to use TypeName to specify that it is a type.
Exception
You cannot use TypeName when nested dependency names are in the base class list or in the member initialization list.
Template class
Drived:public base::nested {//base class list, do not use TypeName public
:
explicit Derived (int x): base: : Nested (x) {//Member initialization list, do not use typename
typename base::nested temp;
...
}
...
};
Some other notes.
1. Nested subordinate names (nested dependent names)
if the name appearing within template is dependent on a template parameter, it is called a subordinate name (dependent names), and if the subordinate name is nested within class, it is called a nested subordinate name (nested dependent names).
For example:
Templaet <typename t>void myprint (const t& T) {
t::const_iterator iter (T.begin ());
Assuming that the parameters in the template parameter list represent a container type, we know that t::const_iterator a dependent template parameter and inside the container, so T::const_iterator is a nested subordinate name.
Before we know what T is, there's no way to know if T::const_iterator is a type, because there might also be a static (static) member variable, consider the following example:
Template <typename t>void myprint (const t& T) {
t::const_iterator * x;
}
If the const_iterator is a static member variable of T, the * in T::const_iterator * x on the above represents multiplication and, if it is a type, declares a pointer to the T::const_iterator type.
This creates confusion for the compiler (because we don't know what T is).
C + + has a rule that when the parser encounters a nested subordinate name in the template, it assumes that the name is not a type unless you specify it with the keyword typename:
Template <typename t>void myprint (const t& T) {
typename t::const_iterator * x; This will not cause confusion.}
The same is true not only internally, but also in the parameter list:
Template <typename t>void f (const t& T, typename t::const_iterator cit) {
//t is not a nested subordinate name, and T::const_iterator is , so we should add typename ///...} in front of T::const_iterator.
2, is nested subordinate name but does not need to add typename two kinds of situations
base class list (base list) and Members initialization list (member Initializaiton list)
base<t>::nested is not allowed in the template <typename t>class derived:public typenamepublic {//base class list:
explicit Derived (int x): base<t>::nested (int x) { //////initialization list is not allowed to use TypeName TypeName Base<t>:: Nested temp; Nested subordinate names (neither in the base class list nor in the initialization list) must precede the TypeName }
}