C 模板特化

2021-05-22 21:57:58 字數 4708 閱讀 2803

對模板特化的理解:

特化整體上分為全特化和偏特化,這一點大家都沒有什麼置疑,但是細分它們各包括哪幾種狀態就很難界定了,而且很多權威的書上都不一致,管它呢,反正我們能會用各種特化就可以了。

下面就談談我個人對特化的劃分和定義:

所謂特化,就是將泛型的東東搞得具體化一些,從字面上來解釋,就是為已有的模板引數進行一些使其特殊化的指定,使得以前不受任何約束的模板引數,或受到特定的修飾(例如const或者搖身一變成為了指標之類的東東,甚至是經過別的模板類包裝之後的模板型別)或完全被指定了下來。

這是網上某個人的一些看法:

模板有兩種特化,全特化和偏特化(區域性特化)

模板函式只能全特化,沒有偏特化(以後可能有)。

模板類是可以全特化和偏特化的。

全特化,就是模板中模板引數全被指定為確定的型別。

全特化也就是定義了乙個全新的型別,全特化的類中的函式可以與模板類不一樣。

偏特化,就是模板中的模板引數沒有被全部確定,需要編譯器在編譯時進行確定。

在型別上加上const、&、*( cosnt int、int&、int*、等等)並沒有產生新的型別。只是型別被修飾了。模板在編譯時,可以得到這些修飾資訊。

我個人也比較贊同這位仁兄的劃分,全特化的標誌就是產生出完全確定的東西,而不是還需要在編譯期間去搜尋適合的特化實現,貌似在我的這種理解下,全特化的東西不論是類還是函式都有這樣的特點,template <>然後是完全和模板型別沒有一點關係的類實現或者函式定義,如果你要說,都完全確定下來了,那還搞什麼模板呀,直接定義不就完事了?但是很多時候,我們既需要乙個模板能應對各種情形,又需要它對於某個特定的型別(比如bool)有著特別的處理,這中情形下就是需要的了。

既然剛才提到了全特化的標誌,那麼再說說其他一些共性的東西:

乙個特化的模板類的標誌:在定義類實現時加上了<>,比如class a;而在定義乙個模板類的時候,class a後面是沒有<>的

全特化的標誌:template <>然後是完全和模板型別沒有一點關係的類實現或者函式定義

偏特化的標誌:template ,就是說還剩下點東西,不像全特化<>整得那麼徹底

首先推薦兩個不錯的**:

先說類模板的特化吧:

誰都沒的說的全特化:

// general version

template

class compare

};// specialize for float

template<>

class compare

};誰都沒的說的偏特化:

template

class a

template

class a

接下來的特化種類,到底劃歸到全特化還是偏特化,你自己看著辦吧,不過大致就以下這些了,逃不出我們的手掌心了:

特化為引用,指標型別:

// specialize for t*

template

class compare

};特化為另外乙個類模板:

// specialize for vector

template

class compare>

}return true;}};

混合型的:

template

class x ;

template

class x, int&> ; //至於這裡怎麼都把t2搞沒了變成只依賴乙個模板引數t了的問題,大家別著急,我來告訴你個本質的東西,把我這麼三點就可以了:1.模板引數個數一致;2.只要template <...>裡面有東西不是<>,比如typename t,那麼特化時就得用到t;3.不進行任何對模板引數的修飾也是不行的,比如templateclass,至少你也得搞個const t之類的吧,呵呵。下面是我搞出來的幾種特殊情況,它們都是正確的:

template

class x {};

template

class x, t&> {};

template

class x, int&> {};

template<>

class x, int&> {};

template

class x, t3&> {};

最後,還有一種超級牛x的,在tr1裡面用以實現function的,以前我都沒見過還可以這麼玩的:

template

class y;//這是在宣告乙個類模板,既然宣告了,以後就得按這個規矩來,在我們之前的程式設計經驗裡,可以重複宣告乙個東西沒問題,但是為同乙個東東重複宣告出不同的東西就不可以了,因此你就不能再宣告諸如templateclass y;這樣的宣告了;其實沒有什麼是不能宣告的,既然我們可以宣告變數,宣告函式,宣告類,那麼當然我們也可以宣告函式模板或者類模板的。

template

class y;//針對帶兩個引數,有返回值的函式型別特化,這裡r (p1,p2)是定義了一種型別,該型別是乙個隱式的函式指標,返回r,引數為p1和p2,這種對函式指標的定義完全等同於r (*)(p1,p2),但是前一種定義很不常見,大家一般是不會注意到這個地方的。

好了,說了不少關於類模板的特化了,下面再簡要說說函式模板的特化:

函式模板的特化只能是全特化,而不能是偏特化,因此對於函式的特化就比較簡單了,就是重新搞一遍就可以了,舉幾個例子如下:

template

t mymax(const t t1, const t t2)

template <>

const char* mymax(const char* t1,const char* t2)

但是你不能這麼搞:

template <>

bool mymax(const char* t1,const char* t2)

其實對於mymax這個模板函式的定義而言,是用乙個模板引數控制了三個地方,那麼你在特化的時候,就也需要用乙個特定的型別修改那三處相應的地方,如果你非要返回bool,那麼你只能再定義乙個函式模板了:

template

bool mymax(const t t1, const t t2)

問題又來了,大家都知道函式過載是不關心返回值的,而只關心引數個數以及型別是否不一致,不一致就是過載,但是對於模板函式而言,這個規矩不再成立,因為任何與模板相關的東西都只是個架子放在那裡而已,只要它符合語法規則就可以了,這些架子只是在有人要呼叫它們時才會發揮效力,也就是說,在編譯的時候會為你搜尋合適的模板函式或者類,只要能找到就ok了,而且還要求是只找到乙個,要是找到多個也不行,呵呵。

其實,對於函式而言,雖然不能偏特化,即不能再在函式名字後面像模板類一樣搞個出來,但是可以通過函式的過載(注意這裡說的過載是指的模板過載,而不是普通意義的函式過載)變通的實現偏特化:

template

bool mymax(t1 t1, t2 t2)

template

bool mymax(t1 t1, int t2)

再談談函式模板引數的推導,大致有以下幾種方法,但是不管怎麼推導,都必須得保證在呼叫函式前能確定模板函式的各個模板引數的型別。

template

t2 fun(t1 arg1, int arg2)

對於上面這種比較特殊的模板函式,你不能通過傳遞引數來自動得到所有模板引數的型別,因此你必須顯示的指定t1和t2的型別,有兩種方法可以實現此目的:

int (*pfun)(double,int) = fun;//借用函式指標定義

cout<(11, 3.2)<

t2 fun(t1 arg1, t2 arg2)

那麼除了上述兩種指定模板引數型別的方法之外,由於該模板函式引數的型別都可以藉由其引數獲得,因此我們省去指定模板引數這一步驟,而直接呼叫該模板函式:

fun(23, 2.3);

最後,再談談非型別模板引數的問題,在《c++ template》的第四章有介紹。

templatestruct stack ;

templateint add(int x)

上面兩個例子分別對應了類和函式兩種情形,有人說非型別的模板引數存在得毫無價值,實則不然,因為我們可以藉由乙個確定的數值來產生一種新的型別或者新的函式。對於上面兩個例子,我覺得用非型別模板引數就很有意義,分別實現了讓使用者指定stack的大小以及指定需要增加的邊際值,關於更多這方面的應用,大家可以在今後的開發過程中逐步發掘,此外,還很有必要強調一下對非型別模板引數的限制,不能使用浮點數、class型別的物件和內部鏈結物件(例如字串常量"hello world!")作為實參;它們可以是常整數(包括列舉值)或者指向外部鏈結物件的指標。

對外部鏈結物件的指標舉個例子:

template

class myclass ;

extern char const s = 」hello」;

myclassx;       //ok

好了,模板這塊內容我先將這麼多。

又從網上搞到點好東東,也貼在這裡吧:

類模板:

* 如果類模板中含有靜態成員,那麼用來例項化的每種型別,都會例項化這些靜態成員。

* 兩個靠在一起的模板尖括號( > ) 之間需要留個空格,否則,編譯器將會認為是在使用operator>>,導致語法錯誤。

* 特化的實現可以和基本類模板的實現完全不同。

* 類模板可以為模板引數定義預設值,稱為預設模板實參,並且他們還可以引用之前的模板引數。

* 成員函式模版不能被宣告為虛函式。

* 類模板不能和另外乙個實體共享乙個名稱。

C 模板 模板特化 模板偏特化

模板是c 的乙個重要特性 使用模板 可以極大的減少類似功能 的編寫 這可以看做是c 相較於c的進步 因為這一特性在c中是不容易達到的 語言層面不支援 模板的關鍵字是 template 簡單的模板應用 template class test int main 使用模板的類在例項化時需要指明模板引數型別...

C 模板特化 偏特化

注意 特化時模板引數的先後順序不能變 特化是基於泛化版本進行的 函式模板特化過載與函式過載不衝突 函式模板只能全特化不能偏特化 模板類泛化 templateclass mytest int m func 模板類全特化 template class mytest 模板類偏特化 templateclas...

c 模板特化偏特化

模板為什麼要特化,因為編譯器認為,對於特定的型別,如果你對某一功能有更好地實現,那麼就該聽你的。模板分為類模板與函式模板,特化分為全特化與偏特化。全特化就是限定死模板實現的具體型別,偏特化就是模板如果有多個型別,那麼就只限定為其中的 一部分,其實特化細分為範圍上的偏特化與個數上的偏特化。模板的泛化 ...