C++模板 全特化、偏特化

C++模板 全特化、偏特化

模板

模板的定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。
模版可以分为两类,一个是 函数模版 ,另外一个是 类模版

函数模板,类模板样例:

/**
 * 作者:lyn
 * 时间:2018.10.30
 * 该程序用来演示函数模板和类模板
 */
#include <iostream>

using namespace std;

//模板函数
template<typename T>
void add(T num1, T num2) {
        cout << num1 << " + " << num2 << " = "<< num1 + num2 << endl;
}

//模板类
template<typename T>
class Test_Class {
public:
        static void multi(T num1, T num2) {
                cout << num1 << " * " << num2 << " = "<< num1 * num2 << endl;
        }
};

int main(){
        //Test 1
        int num1 = 1;
        int num2 = 2;
        add<int>(num1, num2);
        Test_Class<int>::multi(num1, num2);
        //Test 2
        double num3 = 3.1;
        double num4 = 4.2;
        add<double>(num3, num4);
        Test_Class<double>::multi(num3, num4);
        return 0;
}

在这里插入图片描述
函数模板是可以被重载的(类模板不能被重载),也就是说允许存在两个同名的函数模板,还可以对它们进行实例化,使它们具有相同的参数类型。

函数模板重载样例:

/**
 * 作者:lyn
 * 时间:2018.10.30
 * 该程序用来掩饰函数模板的重载
 */
#include <iostream>

using namespace std;

//函数模板
template <typename T>
int fun(T){
        return 1;
}
//函数模板的重载
template <typename T>
int fun(T*){
        return 2;
}

int main(){
        cout << fun<int*>((int*)0) << endl;
        cout << fun<int>((int*)0) << endl;
        return 0;
}

在这里插入图片描述

特化

前面提到函数模板能被重载,而类模板不可以,我们可以通过特化来实现相似的效果,从而可以透明地获得具有更高效率的代码。
特化也分为了两种,全特化和偏特化。

  • 不能将特化和重载混为一谈
    全特化和偏特化都没有引入一个全新的模板或者模板实例。它们只是对原来的泛型(或者非特化)模板中已经隐式声明的实例提供另一种定义。
    在概念上,这是一个相对比较重要的现象,也是特化区别于重载模板的关键之处。
全特化

全特化是模板的一个唯一特例,指定的模板实参列表必须和相应的模板参数列表一一对应。
我们不能用一个非类型值来替换模类型参数。但是如果模板参数具有缺省模板实参,那么用来题还实参就是可选的。

全特化类样例:

/**
 * 作者:lyn
 * 时间:2018.10.30
 * 该程序用来演示全特化类
 */
#include <iostream>
using namespace std;

template<typename T1, typename T2>
class A{
        public:
                void function(T1 value1, T2 value2){
                        cout<<"value1 = "<<value1<<endl;
                        cout<<"value2 = "<<value2<<endl;
                }
};

template<>
class A<int, double>{ // 类型明确化,为全特化类
        public:
                void function(int value1, double value2){
                        cout<<"intValue = "<<value1<<endl;
                        cout<<"doubleValue = "<<value2<<endl;
                }
};

int main(){
        A<int, double> a;
        a.function(12, 12.3);
        return 0;
}                                                                                                                     

在这里插入图片描述

偏特化

偏特化感觉像是介于普通模板和全特化之间,只存在部分的类型明确化,而非将模板唯一化。
再次划重点 函数模板不能被偏特化

偏特化类样例:

/**
 * 作者:lyn
 * 时间:2018.10.30
 * 该程序用来演示偏特化类
 */
#include <iostream>
using namespace std;

template<typename T1, typename T2>
class A{
        public:
                void function(T1 value1, T2 value2){
                        cout<<"value1 = "<<value1<<endl;
                        cout<<"value2 = "<<value2<<endl;
                }
};

template<typename T>
class A<T, double>{ // 部分类型明确化,为偏特化类
        public:
                void function(T value1, double value2){
                        cout<<"Value = "<<value1<<endl;
                        cout<<"doubleValue = "<<value2<<endl;
                }
};

int main(){
        A<char, double> a;
        a.function('a', 12.3);
        return 0;
}

在这里插入图片描述

偏特化的特殊例子
//这段代码是STL源码中的一部分
template <class Iterator>
struct iterator_traits {
  typedef typename Iterator::iterator_category iterator_category;
  typedef typename Iterator::value_type        value_type;
  typedef typename Iterator::difference_type   difference_type;
  typedef typename Iterator::pointer           pointer;
  typedef typename Iterator::reference         reference;
};
/*
 * 偏特化版本,我们可以看到他的唯一不同之处就是T*,这也是偏特化的一种
 */
template <class T>
struct iterator_traits<T*> {
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef ptrdiff_t                  difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};
重点总结
  1. 类模板和函数模板都可以被全特化;
  2. 类模板能偏特化,不能被重载;
  3. 函数模板全特化,不能被偏特化。

模板类调用优先级

对主版本模板类、全特化类、偏特化类的调用优先级从高到低进行排序是:
全特化类>偏特化类>主版本模板类
这样的优先级顺序对性能也是最好的。

猜你喜欢

转载自blog.csdn.net/lyn_00/article/details/83548629