STL源碼剖析(四)模板的特化

STL源碼剖析(四)模板的特化


在STL中,有許多地方使用到了模板的特化,在往下面講解前,我們需要來學習以下什麼是模板的特化,以及爲什麼需要模板的特殊還有其語法

一、什麼是模板的特化?

首先看一個例子

template <class T>
class A
{
public:
    A()
    {
        std::cout<<"T construct"<<std::endl;
    }
};

上述是一個泛化的模板,它支持任何類型

再來看看下面這一個類

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

上述類是對類A的一個特化版本,它僅僅支持int,它是在泛化的模板中的一種具體的特化

你可以嘗試以下運行下面這段代碼

int main(int argc, char* argv[])
{
    A<char> a1; //T construct

    A<int> a2; //int construct

    return 0;
}

你會發現,第一類指定了char類型,它使用的是泛化版本的類模板,第二個類指定爲int類型,它使用了特化爲int類型的類模板

是的,這就是模板的特化,C++對模板的編譯規則是,會先查詢是否有符合當前類型的特殊版本,如果沒有,再使用泛化的版本

就像上面,我們沒有定義char類型的特化版本,所以A<char> a1使用了泛化的類模板,而我們定義了int類型的特化版本,所以A<int> a2使用了特化爲int類型的類模板

二、爲什麼需要模板的特化?

弄明白了什麼是模板的特化後,我們再來討論爲什麼需要模板的特化

首先我們來看一個例子

如果我們使用泛化的模板,那麼使用這個模板的變量必須符合模板中定義的種種規則

如下面

template <class T>
void func(const T& t)
{
    t->print();
}

上述是一個泛化的模板函數,我們的func的目的是要調用對象的print函數來打印這個對象,所以要求所有使用這個模板函數的變量都需要定義有print這個函數

但是事實哪有這麼美好,如果是自定義對象,那麼我們可以很方便的實現print函數,但如果是對於intchar這些原生類型的變量,它們就無法定義自己的print函數,因此也就無法使用func

但是如果我一定要使用func來支持所有類型呢?這個時候,模板特化的作用就體現出來了,我們可以定義intchar等類型的特化版本,如下所示

void func(int value)
{
    std::cout<<value;
}

void func(char vallue)
{
    std::cout<<c;
}

到這裏你應該體會到了特化的作用了吧

模板的特化作用:在一個泛化的模板中,某些類型不適用此泛化的模板函數,或者對於此方法有更優解,那麼這個時候可以特化一個模板來爲其服務

三、模板特化的語法

模板的特化還是挺靈活的,我將其分爲類模板的特化還有函數模板的特化,並舉一些例子,通過這些例子,你就基本可以掌握模板的特化語法

所謂的偏特化與全特化只不過是有沒有將所有的模板參數特化,這裏就不詳細討論了

3.1 類模板的特化

/* 泛化 */
template <class T1, class T2>
class B
{

};

/* 全特化,int類型 */
template<>
class B<int, int>
{

};

/* 偏特化,所有的指針類型 */
template <class T1, class T2>
class B<T1*, T2*>
{

};

/* 偏特化,所有的常量指針類型 */
template <class T1, class T2>
class B<const T1*, const T2*>
{

};

/* 偏特化,只對一個參數進行特化,第二個類型爲char */
template <class T>
class B<T, char>
{

};

3.2 函數模板的特化

/* 泛化 */
template <class T1, class T2>
void func(T1, T2)
{
    
}

/* 全特化 */
void func(int, int)
{
    
}

/* 指針偏特化,所有的指針類型 */
template <class T1, class T2>
void func(T1*, T2*)
{

}

/* 指針偏特化,所有的常量指針類型 */
template <class T1, class T2>
void func(const T1*, const T2*)
{

}

/* 偏特化,只對一個模板進行特化,第二個類型爲int */
template <class T>
void func(T, int)
{

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章