STL運用的C 技術(2) 模板特化

2021-07-08 12:14:02 字數 4704 閱讀 9133

stl是c++標準庫的重要組成部分之一,它不僅是乙個可復用的元件庫,更是乙個包含演算法與資料結構的軟體框架,同時也是c++泛型程式設計的很好例子。stl中運用了許多c++的高階技術。本文介紹模板特化技術的運用。主要參考了《c++ primer》和《stl原始碼剖析》。

stl中大量運用了模組,可以說模板是建立類或函式的公式。但是,我們並不總能寫出對所有可能被例項化的型別都最合適的模板。舉個函式模板特化的例子。

[cpp]view plain

copy

print?

template

<

typename

t>  

intcompare(

const

t &x, 

const

t &y)    

對於上面這個函式模板,如果用兩個字串指標來呼叫,那麼比較的是指標值,也就是比較位址大小,而不是字串的大小。因此為了能夠將compare函式用於字串,就需要提供乙個知道怎麼比較c風格字串的特殊定義。這就是模板特化。

模板特化(template specialization)的定義為指定乙個或多個模板形參的實際型別或實際值。例如可以為compare模板函式定義乙個特化版本。

[cpp]view plain

copy

print?

template

<> 

//template關鍵字後面接空括號

intcompare(

const

char

* const

&x, 

const

char

* const

&y) 

//形參為指向常量的常指標的引用

上文簡單闡述了模板特化,現在介紹模板特化在stl中的運用,以迭代器中的運用為例。

迭代器是stl的關鍵所在,它將原本分開的資料容器和演算法很好的膠合在一起。比如下面這個stl中的函式(摘自原始碼),命名上做了修改,同時略去了一些**,但是足以說明問題。這個函式通過迭代器交換容器的資料,迭代器是資料容器和演算法的橋梁,演算法通過資料容器的迭代器訪問容器中的資料,而不需關心容器的具體構造。

[cpp]view plain

copy

print?

//真正的交換函式,內部呼叫

template

<

class

iter1, 

class

iter2, 

class

t>  

inline

void

_iter_swap(iter1 a, iter2 b, t)   

//交換兩個迭代器所指的元素,外部介面

template

<

class

iter1, 

class

iter2>  

inline

void

iter_swap(iter1 a, iter2 b)   

上面用到了乙個value_type呼叫,注釋說是返回迭代器的值型別,具體如何下文會有介紹。舉這個例子,就是為了引出這個呼叫。本文講的是模板特化,但是到這裡好像已經跑題了,不知所云。鋪墊差不多了,進入正題。

問乙個問題,iter_swap這個函式的形參是迭代器,我們需要在函式內部定義乙個臨時變數,變數的資料型別為迭代器所指的資料型別。那麼我們如何知道迭代器所指的資料型別呢?有人說,可以利用模板實參推斷機制,解決這個問題。**如下所示:

[cpp]view plain

copy

print?

//真正的交換函式

template

<

class

iter1, 

class

iter2, 

class

t>  

inline

void

_iter_swap(iter1 a, iter2 b, t)   

//交換兩個迭代器所指的元素

template

<

class

iter1, 

class

iter2>  

inline

void

iter_swap(iter1 a, iter2 b)   

但是如果要推導函式的返回型別,模板實參推斷機制就失效了。模板實參推斷機制的具體內容,將在本系列(3)中介紹。繼續上面的問題,本文用了乙個稱之為value_type的呼叫來獲取的,它就像是乙個萃取劑,萃取出迭代器所指的資料型別。那麼它是如何實現的呢?答案就是內嵌型別。在stl中,大多數容器要求定義迭代器的內嵌型別,下面是 list 中的定義,已化簡。

[cpp]view plain

copy

print?

class

myalloc;  

template

<

class

t>  

struct

list_iterator;  

template

<

class

t, class

alloc = myalloc>  

class

list;  

通過下面這種方式就可以萃取出 list 迭代器所指的資料型別。

[cpp]view plain

copy

print?

template

<

class

i>  

struct

iterator_traits;  

iterator_traitsint

>::iterator>::value_type x = 1;  

這種方式只能萃取出定義了內嵌型別的迭代器,但是如果是原生指標呢,它是沒有內嵌型別的?比如 vector 容器,它是用原生指標做迭代器的。定義如下:

[cpp]view plain

copy

print?

class

myalloc;  

template

<

class

t, class

alloc = myalloc>  

class

vector :   

;  

模板特化終於登場了,下面加入了原生指標的支援,使用的正是模板特化技術,在泛化設計中加入了特化版本。該技術也是stl中的核心關鍵所在。

[cpp]view plain

copy

print?

template

<

class

i>  

struct

iterator_traits;  

//特化 原生指標

template

<

class

t>  

struct

iterator_traits;  

//特化 原生常指標

template

<

class

t>  

struct

iterator_traits<

const

t*>;  

下面給出了完整的**,已在vs2008下測試通過。

[cpp]view plain

copy

print?

#include 

#include 

#include 

using

namespace

std;  

//萃取劑

template

<

class

i>  

struct

iterator_traits;  

//特化 原生指標

template

<

class

t>  

struct

iterator_traits;  

//特化 原生常指標

template

<

class

t>  

struct

iterator_traits<

const

t*>;  

#define value_type(i) iterator_traits::value_type()

//交換兩個迭代器所指的元素

template

<

class

iter1, 

class

iter2>  

inline

void

iter_swap(iter1 a, iter2 b)   

//真正的交換函式

template

<

class

iter1, 

class

iter2, 

class

t>  

inline

void

_iter_swap(iter1 a, iter2 b, t)   

//測試函式

intmain()    

STL運用的C 技術(3) 模板實參推斷

stl是c 標準庫的重要組成部分之一,它不僅是乙個可復用的元件庫,更是乙個包含演算法與資料結構的軟體框架,同時也是c 泛型程式設計的很好例子。stl中運用了許多c 的高階技術。本文介紹模板實參推斷的運用。主要參考了 c primer 和 stl原始碼剖析 stl利用模板模板實現的,比如它的演算法都是...

STL運用的C 技術(3) 模板實參推斷

stl是c 標準庫的重要組成部分之一,它不僅是乙個可復用的元件庫,更是乙個包含演算法與資料結構的軟體框架,同時也是c 泛型程式設計的很好例子。stl中運用了許多c 的高階技術。本文介紹模板實參推斷的運用。主要參考了 c primer 和 stl原始碼剖析 stl利用模板模板實現的,比如它的演算法都是...

C 模板的特化

ps 在 c 程式設計 特別版 中居然將 特化 翻譯成 專門化 一頭霧水 說起c 的模板及模板特化,相信很多人都很熟悉 但是說到模板特化的幾種型別,相信了解的人就不是很多。我這裡歸納了模板特化的幾種型別,一是特化為絕對型別 而是特化為引用,指標型別 三是特化為另外乙個模板類。這裡用乙個簡單的例子來說...