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++模板详解的主要内容,如果未能解决你的问题,请参考以下文章