【C++】模板具体化、实例化、特化整理总结


模板的具体化分为隐式实例化)、显式实例化和显式具体化)。 模板以泛型的方式描述函数(类),而具体化是使用具体的类型生成函数(类)声明。
显式实例化和显式具体化的区别在于显式实例化只需要写声明不需要写定义,显式实例化的定义与隐式实例化一样由编译器生成。

模板具体化

实例化(隐式实例化)

而是对于实例化模板参数的每种类型,都从模板产生出一个不同的实体。
这种用具体类型代替模板参数的过程叫做实例化。它产生了一个模板的实例。
编译器使用模板为特定类型生成函数(类)定义时,得到的就是模板实例。

template <typename T>
T const& max (T const& a, T const& b)
{
    return  a < b ? b : a;
}

实例化其实就是模板最普通的写法

显式实例化

使用关键字template并指出所需类型来声明类时,编译器将生成类声明的显式实例化。
(显示生成一个类型的实例)

template <typename T>
inline T max (T a, T b)
{
    return  a < b  ?  b : a;
}
template int max<int>(int a, int b);    //显式实例化,指定编译器生成int类型的模板定义
template int max<>(int a, int b);   //简写
template int max(int a, int b); //简写

显式实例化只是一个声明,让编译器用具体的类型生成函数定义或类定义。

用处:
在多文件编译连接时生成实例

//t1.h
template <typename T>
void f(T x);

//t1.cpp
#include "te.h"
#include <iostream>
template <typename T>
void f(T x)
{
    std::cout << x << std::endl;
}
template void f<int>(int);//显式实例化int

//main.cpp
#include "te.h"
#include <iostream>

int main()
{
  f(6); //编译成功,输出6
  //编译失败,undefined reference to `void f<char>(char)'
  f('6'); 
  return 0;
}

上述代码用显示实例化生成了int的函数而没有生成char的,从而报错char类型的未定义

显式具体化(特化)

函数模板特化指函数模板在模板参数为特定类型下的特定实现
模板的特化和函数类模板的重载类似,你可以依次重写这个函数或者类, 也可以只特化某个成员(片特化),也可以特化整个类(全特化)

具体化(全特化)

在起始处声明一个 template<>,接下来声明用来特化类模板的类型。这个类型被用作模板实参,且必须在类名的后面直接指定

template<> 
class A<int>{
    ....
};

进行类模板的全特化时,每个成员函数都必须重新定义为普通函数,原来模板函数中的每个T也相应地被进行特化的类型取代:

#include <iostream>
//模板
template <typename T>
class A{
public:
  void get(){std::cout << "common" << std::endl;}
};

template<>
class A<int>{
public:
  void get(){std::cout << "int template" << std::endl;}
};

int main()
{
  A<std::string> a;
  a.get(); //common
  A<int> aa;
  aa.get(); //int template
  return 0;
}

注意:
全特化和由模板生成的实例化不能存在于同一个程序中。

template <typename T>
class A {
public:
};

template class A<double>;

//错误,必须在其首次使用之前对 类 \"A<double>\" 进行显式专用化
template<> 
class A<double> 
{
};
  • 函数模板特化
template<typename T>
int f(T) { return 1; }

template<> int f<int>(int) { return 3; }    //完整写法
template<> int f(int) { return 3; } //简写,省略了<int>
部分具体化(部分特化、偏特化)

模板偏特化是模板特化的一种特殊情况,指显示指定部分模板参数而非全部模板参数,或者指定模板参数的部分特性分而非全部特性,也称为模板部分特化。

//类模板
template <typename T1, typename T2>
class MyClass {
...
};

//局部特化:两个模板参数具有相同的类型
template <typename T>
class MyClass<T,T> {
...
};

//局部特化:第2个模板参数的类型是int
template<typename T>
class MyClass<T,int> {
...
};

局部特化:两个模板参数都是指针类型。
template<typename T1,typename T2>
class MyClass<T1*,T2*>{
...
};

调用:

Myclass<int,float> mif;   //使用MyClass<T1,T2>
MyClass<float,float> mff;  //使用MyClass<T,T>
MyClass<float,int>  mfi;   //使用MyClass<T,int>
MyClass<int*,float*> mp;   //使用MyClass<T1*,T2*>

实例

#include <iostream>
#include <string>

template <typename T1, typename T2>
class MyClass 
{
public:
    MyClass(const T1& t1, const T2& t2) { std::cout << "111: " << t1 << std::endl; }
};

//显示具体化、特化
template<>
class MyClass<std::string, std::string>
{
public:
    MyClass(const std::string& t1, const std::string& t2) { std::cout << "222 : " << t1 << std::endl; }
};

//部分特化
template <typename T1>
class MyClass<T1, double> 
{
public:
    MyClass(const T1& t1, const double& t2) { std::cout << "333 : " << t1 << std::endl; }
};

//显示实例化
template class MyClass<std::string, int>;

int main()
{
    MyClass<char[3],std::string> class2("s2", "s22"); 
    MyClass<std::string,std::string> class3("s3", "s33"); 
    MyClass<std::string,double> class4("s4", 3.14); 

    return 0;
}

输出

111: s2
222 : s3
333 : s4

  • 39
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
函数模板是一种通用的函数定义,它允许编写能够处理多种不同类型的数据的函数。函数模板的定义以关键字 `template` 开头,后面跟着模板参数列表和函数的原型。 例如,以下是一个简单的函数模板,用于交换两个值: ```c++ template <typename T> void swap(T& a, T& b) { T temp = a; a = b; b = temp; } ``` 上述代码中,`typename T` 表示这是一个类型参数,可以接受任何类型的数据。在函数体中,我们只是简单地交换了两个值。 使用函数模板时,需要将具体的类型传递给模板参数,例如: ```c++ int a = 5, b = 10; swap<int>(a, b); // 交换 a 和 b 的值 ``` 在上述示例中,我们显式地将 `int` 作为模板参数传递给 `swap` 函数。 函数模板还支持全特化,这意味着我们可以为特定的类型提供一个特定的实现。全特化使用关键字 `template<>` 手动指定模板参数列表中的类型,并提供一个特定的函数实现。 例如,以下是一个针对 `char` 类型的 `swap` 函数的全特化: ```c++ template <> void swap<char>(char& a, char& b) { char temp = a; a = b; b = temp; std::cout << "Swapping chars!" << std::endl; } ``` 上述代码中,我们使用了 `template<>` 关键字显示地声明了一个全特化函数,指定了模板参数为 `char`。 当我们调用 `swap` 函数,并将 `char` 类型的变量作为参数传递时,编译器将自动选择调用这个全特化版本的函数。 需要注意的是,全特化版本的函数应该在头文件中进行声明和定义,以便编译器能够正确地实例化这些函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值