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 的模板及模板特化,相信很多人都很熟悉 但是說到模板特化的幾種型別,相信了解的人就不是很多。我這裡歸納了模板特化的幾種型別,一是特化為絕對型別 而是特化為引用,指標型別 三是特化為另外乙個模板類。這裡用乙個簡單的例子來說...