一 概念:


   产生模板的特定类型实例的过程称为 实例化。包括: 类模板的实例化和 函数模板的实例化。


二 类模板实例化

   要使用类模板必须 显示指定模板形参。在类模板的 内部使用时,可以使用类模板的非限定名。

   例如:

template<typename T> 
    class Queue
    {
     public:
     Queue(){}
     Queue(Queue &Q):a(Q.a){}// 等价于Queue<Type>(Queue<Type> &Q):a(Q.a){} 不使用类模板限定。
     private:
     int a;
     };
    Queue <string>queue;

   实际上,当编写Queue<int>时,编译器通过重新编写Queue模板,用类型int代替模板形参的每次出现而 创建Queue<int>类。


三 函数模板实例化

    使用函数模板时,编译器通常会 推断模板实参。


四  模板实参推断(template argument deduction)

    模板实参推断: 从函数实参确定模板实参的类型和值的过程。

   

    1.多个类型形参的实参 必须完全匹配

       例如:

template<typename T>
                   void test1(T &t1,T &t2)
                   {
                       cout<<t1<<"\n"<<t2<<endl;
                        }

                 调用:

int t1=1;
                            short int t2=2;
                            test1(t1,t2);// 错误,形参与实参类型完全匹配,不允许常规转换。

                  如果需要常规转化:函数必须用两个类型形参来定义。

template<typename T1,typename T2>
                   void test1(T1 &t1,T2 &t2)
                   {
                       cout<<t1<<"\n"<<t2<<endl;
                        }


      2.  类型形参的实参的 受限转换

          一般而言,不会转换实参以匹配已有的实例化,相反,会产生新的实例。

           除了产生新的实例外,编译器只执行两种转换:


          const转换:可以用非const对象的指针或引用来调用接受const指针或const引用的函数;如果函数接受非引用形参,形参类型和实参类型都忽略const。


           数组或函数到指针的转化:如果模板形参不是引用类型,则对数组和函数类型的实参应用常规指针转换。

                   

五   函数模板的 显式形参

   在某些情况下,不可能推断模板实参的类型,那么就有必要覆盖模板实参推断机制,并显式指定为模板形参所用的类型或值。

六  非类型模板形参和 非模板形参


    1. 非类型模板形参:模板形参不必都是类型。

       

       函数模板非类型形参和类模板非类型形参: 在需要常量表达式时可以使用非类型形参,非类型实参必须是常量表达式