天天看點

4-6類和函數的模闆全特化、偏特化(局部特化)1.類模闆特化2.函數模闆特化3.模闆特化版本放置位置建議

目錄

1.類模闆特化

1.1類模闆全特化

1.1.1正常全特化

1.1.2類模闆偏特化(局部特化)

2.函數模闆特化

2.1 函數模闆全特化

2.2 函數模闆不能偏特化

3.模闆特化版本放置位置建議

1.類模闆特化

特化:相反的是   泛化:模闆,可以随便指定類型

特化:對特殊的類型(類型模闆參數)進行特殊的對待。

1.1類模闆全特化

1.1.1正常全特化

必須先有泛化版本才能存在特化版本。隻要設計特化,就一定存在泛化

特化版本代碼編譯器會優先選擇

#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;
}
           

4-6類和函數的模闆全特化、偏特化(局部特化)1.類模闆特化2.函數模闆特化3.模闆特化版本放置位置建議

特化成員函數而不是模闆

#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
template <typename T , typename U>
struct TC   //泛化的TC版本
{
    TC()
    {
        cout <<"泛化版本的構造函數" << endl;
    }
    void function()
    {
        cout << "泛化版本" << endl;
    }
};

template <>
void TC<int ,int>:: function ()
{
    cout << "int int的function()特化版本" << endl;
}

int main()
{
    TC<int,int> tech; //調用泛化版本的構造函數
    tech.function();  //因為我們特化了int ,int類型的
}
           

1.1.2類模闆偏特化(局部特化)

偏特化從兩個方面說起:一個是從 模闆數量,一個是從模闆參數範圍上。

#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
template <typename T , typename U ,typename W>
struct TC
{
    void functest()
    {
        cout << "泛化版本"  <<endl;
    }
};
//從參數數量上進行偏特化,我們現在綁定2個類型模闆參數
template <typename U>
struct TC<int,U,double> //這裡可以跳轉
{
    void functest()
    {
        cout <<"偏特化版本" <<endl;
    }
};
int main()
{
    //數量上
    TC<double,int,double> tech;
    tech.functest();
    TC<int ,int ,double> tech1;
    tech1.functest();
}
           
#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;
}

           

    模闆參數範圍上,int ---- const int (比int小)

    T到T*,縮小了

    T到 T& T&&  (右值引用)

4-6類和函數的模闆全特化、偏特化(局部特化)1.類模闆特化2.函數模闆特化3.模闆特化版本放置位置建議

2.函數模闆特化

2.1 函數模闆全特化

全特化函數模闆實際上等價于執行個體化 一個函數模闆,并不是等價于一個函數重載。

//void tfunc<int ,double>(int &,double &){}  全特化,等價于執行個體化一個函數模闆

//void tfunc (int &tmp1,double &temp2) {} 函數重載

#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);
    //編譯器選擇最合适的版本:普通函數 > 特化版本 > 泛化版本;

    //全特化函數模闆實際等價于執行個體化一個函數模闆,并不是函數重載。
    //void tfunc<int, double>(int &tmpv1, double &tmpv2){ }
    //void tfucn(int &tmpv1, double &tmpv2) { }

    system("pause");
    return 0;
}
           

//編譯器選擇最合适:普通優先,特化版本,泛化版本

//數組類型模闆參數,比 指針類型模闆參數更合适。

如果你傳遞字元串給函數模闆,函數模闆的特化版本中有 數組類型模闆參數, 指針類型模闆參數。

編譯器會認為 數組類型模闆參數比指針類型模闆參數更合适。 是以編譯器會為你選擇數組類型的模闆參數 的特化版本。

2.2 函數模闆不能偏特化

寫法就沖突了:C++不支援函數模闆偏特化,隻能全特化。

3.模闆特化版本放置位置建議

模闆定義。實作都放在一個.h的檔案中

模闆的特化版本泛化版本,實作都放在同一個.h檔案中

.h檔案中前邊放泛化版本,後邊放特化版本。