模板顯式 隱式例項化和(偏)特化 具體化的詳細分析

2021-07-25 20:47:39 字數 3964 閱讀 3118

最近看了看到了模板的特化,突然想起來上說的顯式具體化、隱式具體化、特化、偏特化、具體化等概念弄得頭暈腦脹,我在網上了找了好多帖子,才把概念給理清楚。

一下是我把再網上找的資料整理一下。

看著這麼多叫法,其實就是三種。

1. 顯示例項化

2. 隱式例項化

3. 特化(=具體化)、偏特化

一、例項化

1.顯示、隱式例項化

什麼是例項化:乙個通過使用具體值替換模板引數,從模板產生的普通類,函式或者成員函式的過程。

顯示例項化:通過名字可見,就是清楚的表明你要例項化的型別

隱式例項化:通過編譯器自己推測判斷要例項化的型別。

比如乙個模板:

[cpp]view plain

copy

print?

template

<

class

t> 

//函式模板實現

void

swap(t &a, t &b)    

a. 顯示例項化

template  void swap();  // 無須給該函式重新編寫函式體,這只是個宣告

為什麼要顯示例項化? 

主要是提高效率,當顯式例項化模板時,在使用模板之前,編譯器根據顯式例項化指定的型別生成模板例項,這樣就相當於本程式裡面有個一

[cpp]view plain

copy

print?

void

swap(

int&a, 

int&b)    

這樣的話,每次需要呼叫 swap(a,b)的時候每次都重新生成該型別的**,可以節省空間,也能提高效率。這就是為什麼要是顯式的例項化的原因。

b. 隱式例項化

隱式例項化指的是:在使用模板之前,編譯器不生成模板的宣告和定義例項。只有當使用模板時,編譯器才根據模板定義生成相應型別的例項。

int i=0, j=1;

swap(i, j); //編譯器根據引數i,j的型別隱式地生成swap(int &a, int &b)的函式定義。

隱式例項化就是程式設計師為了省事,把型別省略讓編譯器判斷,這是乙個偷懶的表現吧。

二、特化

1.  特化(=具體化)

然而通常又有一些特殊的情況,不能直接使用泛型模板展開實現,這時就需要針對某個特殊的型別或者是某一類特殊的型別,而實現乙個特例模板————即模板特化

當t如果為 乙個 struct型別的,它的交換就無法進行,所以我們針對這種特殊的情形,我們專門寫了乙個函式,只有當t為 這種struct型別時候,才會呼叫這個特化的函式

[cpp]view plain

copy

print?

//對函式

#define maxname 128

struct

job  

;  template

<

class

t>  

void

swap(t &a, t &b )  

;  template

void

swap<

int>(

int&a, 

int& b);  

//顯式例項化,只需宣告

template

<> 

void

swap(job &a, job &b)   

//顯式具體化(上面已經講過,注意與例項化區分開,必須有定義)

;//explicite specialization.

//對類模板:

template

<

class

t>  

class

arrary  

;//template class declaration.

template

class

array<

int>;   

//explicit instantiation. 顯式例項化

template

<> 

class

array

;//expicit specialization.   顯式具體化,類定義體可以不同於類模板array

2. 偏特化

模板的偏特化是指需要根據模板的部分引數進行特化。

a. 類模板的偏特化

例如c++標準庫中的類vector的定義

[cpp]view plain

copy

print?

template

<

class

t, class

allocator>  

class

vector ;

template

<

class

allocator>  

class

vector<

bool

, allocator> ;

//這個偏特化的例子中,乙個引數被繫結到bool型別,而另乙個引數仍需要由使用者使用時指定。

b. 函式模板的偏特化

網上看到有人說:從嚴格意義上講,函式模板並不支援偏特化(我對這個不是很理解),但由於可以對函式進行過載,所以可以達到類似於類模板偏特化的效果。

比如:a) template void f(t); 

根據過載規則,對a)進行過載

b) template < class t> void f(t*); 

如果將a)稱為基模板,那麼b)稱為對基模板a)的過載,而非對a)的偏特化。

這裡我就不深入的剖析偏特化了。

三、模板的匹配順序

(1) 

類模板的匹配規則

最優化的優於次特化的,即模板引數最精確匹配的具有最高的優先權

例子:template 

t> 

class 

vector; 

// (a) 

普通型template 

t> 

class 

vector; 

// (b) 

對指標型別特化

template 

<> 

class 

vector 

; // 

(c) 

對void*進行特化

每個型別都可以用作普通型(a)的引數,但只有指標型別才能用作(b)的引數,而只有void*才能作為(c)的引數

(2) 

函式模板的匹配規則

非模板函式具有最高的優先權。如果不存在匹配的非模板函式的話,那麼最匹配的和最特化的函式具有高優先權

例子:template 

t> 

void 

f(t); 

// (d)

template 

t> 

void 

f(int, 

t, double); 

// (e)

template 

t> 

void 

f(t*); 

// (f)

template 

<> 

void 

f(int) 

; // 

(g)void 

f(double); 

// (h)

bool 

b;int 

i;double 

d;f(b); 

// 以 

t = 

bool 

呼叫 (d)

f(i,42,d) 

// 以 

t = 

int 

呼叫(e)

f(&i) 

; // 

以 t 

= int* 

呼叫(f)

f(d); 

// 呼叫(h)

模板顯式 隱式例項化和(偏)特化 具體化的詳細分析

最近看了看到了模板的特化,突然想起來上說的顯式具體化 隱式具體化 特化 偏特化 具體化等概念弄得頭暈腦脹,我在網上了找了好多帖子,才把概念給理清楚。一下是我把再網上找的資料整理一下。看著這麼多叫法,其實就是三種。1.顯示例項化 2.隱式例項化 3.特化 具體化 偏特化 一 例項化 1.顯示 隱式例項...

模板顯式 隱式例項化和(偏)特化 具體化的詳細分析

最近看了看到了模板的特化,突然想起來上說的顯式具體化 隱式具體化 特化 偏特化 具體化等概念弄得頭暈腦脹,我在網上了找了好多帖子,才把概念給理清楚。一下是我把再網上找的資料整理一下。看著這麼多叫法,其實就是三種。1.顯示例項化 2.隱式例項化 3.特化 具體化 偏特化 一 例項化 1.顯示 隱式例項...

C 模版 顯式例項化 顯式具體化 隱式例項化

helloword的部落格 函式模板是c 新增的一種性質,它允許只定義一次函式的實現,即可使用不同型別的引數來呼叫該函式。這樣做可以減小 的書寫的複雜度,同時也便於修改 注 使用模板函式並不會減少最終可執行程式的大小,因為在呼叫模板函式時,編譯器都根據呼叫時的引數型別進行了相應例項化 下面來看看函式...