城市故事诗与诗写作大家园📝(夕雅编)

C++模板与泛型 --- 模板全特化、偏特化(局部特化)

2019-06-09  本文已影响3人  307656af5a04

一、类模板特化

特化与泛化相反,泛化可以随便指定类型
特化就是对特殊的类型(类型模板参数)进行特殊的对待,给它写适合它的专用代码。

1、类模板全特化

a、常规全特化

#include <iostream>
#include <string>

using namespace std;

template <typename T,typename U>
struct TC // 泛化的TC类模板
{
    TC()
    {
        cout << "泛化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "泛化版本" << endl;
    }
};

// 当T与U这两个类型模板参数都为int类型时,我们希望做一个特化版本
// 全特化就是所有类型模板参数,都需要用具体的类型代表
// 全特化表示所有类型模板参数都用具体类型代表,
// 所以这里template后面的<>里为空
template <> 
struct TC<int,int> // 上面的T绑定到第一个int,上面的U绑定到第二个int
{
    TC()
    {
        cout << "特化版本构造函数" << endl;
    }
    // 对特化版本进行单独处理
    void functest()
    {
        cout << "int,int的特化版本" << endl;
    }
};

// 当T与U这两个类型模板参数都为int类型时,我们希望做一个特化版本
// 全特化就是所有类型模板参数,都需要用具体的类型代表
// 全特化表示所有类型模板参数都用具体类型代表,
// 所以这里template后面的<>里为空
template <> 
// 上面的T绑定到第一个double,上面的U绑定到第二个int
struct TC<double, int> 
{
    void functest()
    {
        cout << "double,int的特化版本" << endl;
    }
};

int main()
{
    // 调用int,int特化版本
    TC<int, int> dc;
    dc.functest();

    // 调用泛化版本
    TC<char, int> tchar;
    tchar.functest();

    system("pause");
    return 0;
}

b、特化成员函数而不是模板

// 全特化
template <>
void TC<double, double>::functest()
{
    cout << "double,double特化版本函数";
}

// 调用
// 调用的是泛化版本的构造函数
TC<double, double> dx;
// 调用的是特化版本的函数
dx.functest();

2、类模板偏特化(局部特化)
偏特化从两个方面说起:一个是从模板参数数量上,一个是从模板参数范围上

a、模板参数数量

#include <iostream>
#include <string>

using namespace std;

template <typename T,typename U, typename W>
struct TC // 泛化的TC类模板
{
    TC()
    {
        cout << "泛化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "泛化版本" << endl;
    }
};

// 从参数数量上进行偏特化,绑两个类型模板参数,留一个类型模板参数
template <typename U>
struct TC <int,U, int>
{
    TC()
    {
        cout << "偏特化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "偏特化int,U, int版本" << endl;
    }
};

int main()
{
    // 偏特化版本
    TC<int, int, int> dc;
    dc.functest();
    system("pause");
    return 0;
}

b、模板参数范围

int --> const int (比int范围小)
T --> T(从任意类型T缩小为指针类型T)
T --> T&(左值引用)或者T&&(右值引用)都叫范围缩小

#include <iostream>
#include <string>

using namespace std;

template <typename T>
struct TC // 泛化的TC类模板
{
    TC()
    {
        cout << "泛化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "泛化版本" << endl;
    }
};

// 模板参数范围上的特化版本
template <typename T>
struct TC<const T>
{
    TC()
    {
        cout << "const类型特化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "const类型特化版本" << endl;
    }
};

// 模板参数范围上的特化版本
template <typename T>
struct TC<T*>
{
    TC()
    {
        cout << "指针类型偏特化版本构造函数" << endl;
    }

    void functest()
    {
        cout << "指针类型特化偏版本" << endl;
    }
};

int main()
{
    // 模板参数范围上的特化版本
    TC<const int> dc;
    dc.functest();

    // 模板参数范围上的特化版本
    TC<int *> dx;
    dx.functest();

    system("pause");
    return 0;
}

局部特化,特化完了之后它本质上还是一个模板;
全特化,特化完了之后就等于一个具体的类;


二、函数模板特化

1、函数模板全特化

#include <iostream>
#include <string>

using namespace std;

// 函数模板泛化版本
template <typename T,typename U>
void tfunc(T &tmprv, U &tmprv2)
{
    cout << "tfunc泛化版本!" << endl;
    cout << tmprv << endl;
    cout << tmprv2 << endl;
}

// 函数模板全特化版本 T =int ,U = double
template <>
void tfunc(int &tmprv, double &tmprv2)
{
    cout << "tfunc特化版本!<int, double>" << endl;
    cout << tmprv << endl;
    cout << tmprv2 << endl;
}

// 函数模板重载函数
void tfunc(int &tmprv, double &tmprv2)
{
    cout << "tfunc重载函数版本" << endl;
    cout << tmprv << endl;
    cout << tmprv2 << endl;
}

int main()
{
    const char *p = "I Love China!";
    int i = 12;
    // 泛化版本
    tfunc(p, i);

    // 特化版本
    int x = 1; double y = 3;
    tfunc(x, y);
    //编译器选择最合适的版本:普通函数 > 特化版本 > 泛化版本;

    system("pause");
    return 0;
}

2、函数模板偏特化

函数模板不存在偏特化;


三、模板特化版本放置位置建议

模板的定义与实现都放在.h文件中;
模板的特化版本与泛化版本都应该放在同一个.h文件中,文件的前面放泛化版本,后面放特化本本;


上一篇 下一篇

猜你喜欢

热点阅读