PS:
template template parameters (double template parameters) are class templates placeholders, which are declared in a manner similar to class templates.
Parametric declaration
The difference between template and class or function is that the template declaration statement has a parameterized clause:
template <...parameters here...>
Or:
export template <...parameters here>
The following two templates are shown: one is within the class, i.e. member templates, and the other is outside the class and within the namespace scope (global scope is also known as a namespace scope):
template <typename T>
class List{//namespace scope class template
public:
template <typename T2>
List(List<T2> const&);//member function template
...
};
template <typename T>
template <typename T2>
List<T>::List(List<T2> const& b){
...
}
template <typename T>
int Length(List<T> const&);//namespace scope function template
class Collection{
template<typename T>
class Node{//member class template
...
};
template <typename T>
class Handle;//member class template, undefined
template <typename T>
T* alloc(){//member function template,Imply as inline function
...
}
...
};
template <typename T>
class Collection::Handle{//member class template
...
};
member templates outside the definition domain class can have multiple templates < <... >... > Parametric clauses, one of which represents the template itself, and the other clauses represent each layer of class template on the periphery. These clauses must start with the outermost class templates.
Functiontemplate can have a default call argument, just like general function:
template <typename T>
void report_top(Stack<T> const&,int number=10);
template <typename T>
void fill(Array<T>*,T const&=T());//If T is built-in, T() is 0 or false
When fill() is called, if the caller provides a second argument value, the default argument will not be instantiated, which ensures that compilation errors will not occur if the default argument cannot be instantiated for a particular type of T. Examples are as follows:
class value{
public:
Value(int);
};
void init(Array<Value>* array){
Value zero(0);
fill(array,zero);//OK
fill(array);//ERROR: Value has no default constructor, so the call failed
}
In addition to the two basic types of templates, three other declarations can also be parameterized, all of which correspond to the member definitions of the class template:
1) the definition of member functions of class templates;
2) the definition of nested class members (nested class members) of class templates;
3) static member variable definition of class templates.
Although they can also be parameterized, they are not first-level templates. Their parameters are determined entirely by the template to which they belong. Examples are as follows:
template <int I>
class CupBoard{
void open();
class Shelf;
static double total_weight;
...
}
template <int I>
void CupBoard<T>::open(){
...
}
template <int I>
class CupBoard<I>::Shelf{
...
};
template <int I>
double CupBoard<I>::total_weight=0.0;
- Virtual member function
The reason that member function templates cannot be declared virtual is that the virtual function calling mechanism uses a fixed-size table in which each entry records a virtual function entry. However, it is not known how many member function templates need to be instantiated until the entire program is compiled, so it conflicts with the virtual function calling mechanism.
But class template members can be virtual functions, because when class is instantiated, the number of member function s is already determined, so it can be virtual functions.
template <typename T>
class Dynamic{
public:
//class template Of member function,Can be declared asvirtual
virtual ~Dynamic();
//member function template, cannot be declared virtual
template <typename T2>
virtual void copy(T2 const&);
};
- Naming mechanism of template
Each template must have a unique name in its scope unless it is overloaded function templates. It's important to note that class template can't share the same name with other different kinds of objects, which is different from the general non-template class.
int C;
class C;//class names and nonclass names are in different spaces
int X;
template <typename T>
class X;//ERROR: Name conflicts with variable X above
struct S;
template <typename T>
class S;//ERROR: Name conflicts with the above struct S
template usually uses external links, but can't use C links. The only exception is static namespace scope function templates. template can't be declared inside the function by default:
extern "C++" tempalte <typename T>
void normal();
There is also a non-standard form of links
extern "Xroma" template <typename T>
void Xroma_link();
tempalte <typename T>
void external();//Shoot directly at objects of the same name and scope in another file
tempalte <typename T>
static void internal();//It has nothing to do with the template of the same name in another file
- Primary Template
The declaration statement of the main template does not add a template argument list enclosed in angle brackets after the template name:
template <typename T> class Box;//OK:primary template
template <typename T> class Box<T>;//error:non-primary template
template <typename T> void translate(T*);//ok:primary template
template <tyepname T> void translate<T>(T*);//error:non-primary template
Once we declare a partial template, a non-primary template is generated.
Template Parameter
There are three types of template parameters:
1) Type parameters (type parameters):
2) Nontype parameters (untyped parameters):
3) template template parameters (double template parameters).
template parameters are variables of life in the parameterized clause of the template declaration statement. template parameters are not necessarily named:
template <typename,int>
class X;
But when template parameters need to be used in template code, the latter must be named. Note that template parameters declared later can use the name of template parameters declared earlier:
template <typename T,T* Root,template <T*> class Buf>
class Structure;
Now let's break each one.
- Type Parameters
Category parameters are imported by keyword typename or class, which are completely equivalent. The keyword typename or class is followed by a simple identifier, which can be followed by a comma to partition the next parameter, or a closing clause with a right-hand bracket, or an equal sign to represent the preset template independent variable.
The function of type parameter in template declaration statement is very similar to the name of typedef. For example, you can't use a name like class T. Timely T does represent a class.
template <typename Allocator>
class List{
class Allocator* allocator;//ERROR
friend class Allocator;//ERROR
...
};
- Nontype Parameters
The essence of untyped parameters is that the constants of their values can be determined at compile time or link time. The type of this parameter must be one of the following three:
Integer (int) or enum type;
pointers: point to regular objects, perform functions, and point to members;
reference: Points to objects and functions.
You may be surprised to find that there is typename in front of non-type parameter, as shown below:
template <typename T,typename T::Allocator* Allocator>
class List;
Nontype parameters can also be function or array types, but they all degenerate into corresponding pointer types:
template<int buf[5]>
class Lexer;
tempalte <int* buf>
class Lexer;
Nontype template param
Te eters'declaration protection four is very similar to variable declarations, but you can't add modifiers like static, mutable, but you can add const or volatile, but if these modifiers appear at the outermost level of parameter types, the compiler will ignore them:
template <int const length> //const is ignored
class Buffer;
template <int length>
class Buffer;//Equivalent to the previous line declaration statement
Finally, it is emphasized that non-type parameters are always right values: they cannot be addressed or assigned.
Template Template Parameters
Template Template Parameter is a class template placeholder, which is declared in a manner similar to class templates, but cannot use the keywords struct and union.
template <template<typename X> class C>//OK
void f(C<int>* p);
template <template<typename X> struct C>//ERROR: The keyword struct cannot be used
void f(C<int>* p);
template <template<typename X> union C>//ERROR: Can't use the keyword union
void f(C<int>* p);
Within their scope, you can use template parameters as you would use class template.
Template template parameters can also have default template arguments (default template arguments). If the client does not specify variables for the corresponding parameters, the compiler will use these preset variables:
template <template <typename T,typename A=MyAllocator> class Container>
class Adaptation{
Container<int> storage;//Equivalent to Container < int, MyAllocator >
...
};
In template template parameter s, the name of template parameter can only be used in other parameter declarations of template parameter, as shown below:
template <template<typename T,T*> class Buf>
class Lexer{
static char storage[5];
Buf<char,&lexer<Buf>::storage[0]> buf;
...
};
template <template<typename T> class List>
class Node{
static T* storage;//ERROR: template template parameters cannot be used hereT
...
};
In order to prevent the problems mentioned above, the template parameters name in template template parameter is not usually used elsewhere. Therefore, template parameters that are not used can be anonymous. Examples are as follows:
template <template <typename,typename=MyAllocator> class Container>
class Adaption{
Container<int> storage;//Equivalent to Container < int, MyAllocator >
...
};
- Default Template Arguments
You can refer to this blog for setting default template parameters: default template arguments for both function and class templates
No matter what template parameters can have default variables, of course, it must match the corresponding parameters. Obviously, the default template variables can not depend on their own parameters, but can depend on the parameters declared before:
template <typename T,typename Allocator=allocator<T> >
class list;
Like the presupposed independent variables of a function, the condition that a parameter has a presupposed independent variable is that all subsequent parameters have presupposed independent variables.
Usher arguments for subsequent parameters are usually unloaded in the same template declaration statement, but can also be written in an earlier declaration statement of the template. For example:
template <typename T1,typename T2,typename T3,typename T4=char,typename T5=char>
class Quintuple;//OK
template <typename T1,typename T2,typename T3=char,typename T4,typename T5>
class Quintuple;//OK
template <typename T1=char,typename T2,typename T3,typename T4,typename T5>
class Quintuple;//ERROR:T1 cannot have default values because T2 does not have default values
At the same time, we cannot repeat the default template argument.
template <typename T=void>
class Value;
template <typename T=void>
class Value;//ERROR: Presupposed variables are redefined
Unfinished...