• c++模板详解


    写在前面:函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型(如int或double)替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。由于模板允许以泛型(而不是具体类型)的方式编写程序,因此有时也被称为通用编程。由于类型是用参数表示的,因此模板特性有时也被称为参数化类型(parameterized types)。

    创建模板,关键字template和typename是必需的,除非可以使用关键字class代替typename。另外,必须使用尖括号。如下程序所示:

    template <typename T>
    void swap(T &a, T &b)
    {
        T temp;
        temp = a;
        a = b;
        b = temp;      
    }

    注意:模板并非函数定义,但使用了int的模板实例是函数定义。

    (1)隐式实例化:

    最初,编译器只能通过隐式实例化,来使用模板生成函数定义,这也是我们最常用的方法;如可以像下面这样使用上面定义的函数模板:

    short a, b;
    swap(a, b); // T 为 short 类型
    int c, d;
    swap(c, d); // T 为 int 类型

    使用上面的例子程序,我们可以交换两个同类型(int,double……)的值,当如果T为数组、指针或者结构,那么编写的模板函数就无法处理这些类型了,一种方案是重载C++运算符;另一种方案是,为特定类型提供具体化的模板定义,下面就介绍集几种方案。

    (2)显式实例化:

    现在C++还允许显式实例化(explicit instrantiation)。这意味着可以直接命令编译器创建特定的实例,如swap<int>()。其语法是,声明所需的种类——用<>符号指示类型,并在声明前加上关键字template:

    #include <iostream>
    using namespace std;
    
    namespace zcc {  //命名空间
        template <typename T>  //模板(不是函数定义)
        void swap(T& a, T& b)
        {
            T temp = a;
            a = b;
            b = temp;
        }
    
        template void swap<int>(int& a, int& b);  //显式实例化
    
    }
    
    int main()
    {
        int a = 3;
        int b = 4;
        zcc::swap(a, b);
        cout << a << endl;
        return 0;
    }

    实现了这种特性的编译器看到上述声明后,将使用swap()模板生成一个使用int类型的实例。也就是说,该声明的意思是"使用swap()模板生成int类型的函数定义。"

    (3)显式具体化:

     与显式实例化不同的是,显式具体化使用下面两个等价的声明之一:

    template <> void swap<int> (int &, int &);     //explicit specialization
    template <> void swap (int &, int &);     //explicit specialization

    具体的实例如下:

    #include <iostream>
    using namespace std;
    
    namespace zcc {  //命名空间
        template <typename T>  //模板(不是函数定义)
        void swap(T& a, T& b)
        {
            T temp = a;
            a = b;
            b = temp;
        }
        template <> void swap<int>(int& a, int& b) //隐式实例化
        {
            int temp;
            temp = a;
            a = b;
            b = temp;
        }
    
    }
    
    int main()
    {
        int a = 3;
        int b = 4;
        zcc::swap(a, b);
        cout << a << endl;
        return 0;
    }

    显式实例化和显式具体化区别在于:这些声明的意思是“不要使用swap()模板来生成函数定义,而应使用专门为int类型显式地定义的函数定义。”这些原型必须有自己的函数定义。显式具体化声明在关键字template后包含<>,而显式实例化没有。

     警告:试图在同一个文件中(或转换单元)中使用同一种类型的显式实例化和显式具体化 将出错。

     隐式实例化、显式实例化和显式具体化统称为具体化(specialization)。它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述。

    (4)部分具体化:

    C++还允许部分具体化(partial speciazation),即部分限制模板的通用性。例如,部分具体化可以给类型参数之一指定具体的类型:

    // general template
    template <typename T1, typename T2> class Pair { …… };
    // specialization with T2 set to int
    template <typename T1> class Pair<T2, int> { …… }; 

    关键字template后面的<>声明的是没有被具体化的类型参数。因此,上述第二个声明将T2具体化为int,但T1保持不变。注意,如果指定所有的类型,则<>内将为空,这将导致显式具体化:

    // specialization with T1 and T2 set to int
    template <> class Pair<int, int> { …… }; 

    注意:如果有多个模板可供选择,编译器将使用具体化程度最高的模板。

    参考:https://www.cnblogs.com/yyxt/p/4256022.html

  • 相关阅读:
    文件IO流
    ArrayList LinkedList vector的区别
    双例集合Map,HashMap常用方法及源码分析
    单例集合List和Set
    集合与数组
    自然排序与定制排序
    String StringBuffer StringBuilder
    String与其他结构的转化
    线程的通信
    死锁,同步锁
  • 原文地址:https://www.cnblogs.com/USTC-ZCC/p/13938904.html
Copyright © 2020-2023  润新知