c++模板详解

Posted ustc-zcc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于c++模板详解的主要内容,如果未能解决你的问题,请参考以下文章

算法基础| 差分算法及模板详解

算法基础| 前缀和算法及模板详解

算法基础:离散化及模板详解

Python中verbaim标签使用详解

C++ 模板详解(转)

详解C++多线程