c++非型別模板引數的限制在 c++ templates中有兩條:
1. 引數是常整數(包括列舉值)
2. 指向外部鏈結物件的指標
英文的原文(摘錄自c++ templates 4.3)如下:
note that nontype template parameters carry some restrictions. in general, they may be constant integral values (including enumerations) or pointers to objects with external linkage.
這裡面說的有點費解,對這裡面的論述稍微做點註解。
引數指的是實參,在函式中關於引數的術語有parameter和argument兩種,前者指的是函式的形參,而後者是指真正傳入的引數值,如下所示:
//這裡的引數a和b指的是形參(parameter)
int add(int a, int b)
int main()
因此上面的關於非型別模板實參的描述應該是:實參是整型或者列舉型別。舉例如下:
template
int addvalue(int x)
這個示例就是乙個正確的非型別模板引數的函式模板,它的模板引數的定義書寫方式和我們在定義普通的int型別變數是沒有任何差別。
當我看到條款1時,我的第一反應是這個示例是不對的,應該是常量或者列舉值呀。寫成下面的方式:
template
const intval>
int addvalue(int x)
事實上這兩種寫法都是對的,後一種寫法對intval有一些限制,intval必須是常量因此不能在函式體內修改它。
也就是說我第一反應的理解並不正確,我的第一反應是對形參的要求,但是實際上這個條款是對實參的要求,如下所示:
int main()
; int a = addvalue(v);
std::cout
<< a << std::endl;
//模板引數是int型別的變數,不是常量(編譯出錯)
int int6 = 6;
int t = addvalue(v);
std::cout
<< t << std::endl;
}
指向外部鏈結物件的指標,這裡有兩層含義:1.非型別模板形參可以是指標;2.指標指向的物件必須是具有外部鏈結性的物件(另外物件必須必須是編譯時常量表示式)
這裡面涉及到外部鏈結和內部鏈結的概念,這些和c/c++中的編譯過程和編譯單元相關,可以檢視參考文獻中的文章。參考文獻3種詳細的提及了對實參和形參的要求:
這裡要強調一點,我們對於非型別形參的限定要分兩個方面看
1.對模板形參的限定,即template
<>裡面的引數
2.對模板實參的限定,即例項化時<>裡面的引數
【對形參的要求】
1.字串不可以作為非型別形參
2.整形,可轉化為整形的型別都可以作為形參,比如int,char,long,unsigned,bool,short(enum宣告的內部資料可以作為實參傳遞給int,但是一般不能當形參)
3.指向物件或函式的指標與引用(左值引用)可以作為形參
【對實參的要求】
1.**實參必須是編譯時常量表示式,不能使用非const的區域性變數,區域性物件位址及動態物件**[非常重要]
2.非const的全域性指標,全域性物件,全域性變數都不是常量表示式。
3.由於形參的已經做了限定,字串,浮點型即使是常量表示式也不可以作為非型別實參
備註:常量表示式基本上是字面值以及const修飾的變數
3.1 非型別模板形參不能為浮點型別
模板引數(形參)不能是浮點型別,也就是下面的**編譯會出錯
//形參不能為浮點型別
//在c++11、c++14中測試依然報錯
template
double process(double v)
c++ templates一書作者提到這一特性的實現是可以實現的,未來c++的標準可能會支援,但是在c++11和c++14種仍然是不支援的。
3.2 非型別模板形參不能為類(class)
下面的**編譯會出錯:
template
class myclass
;
參考文獻
c++ templates: the complete guidestatic inline與內部、外部鏈結物件
模板非型別形參的詳細闡述
非型別模板引數
這是 c templates 第四章的學習筆記。這一章和下一章可以看作是對前面介紹的函式模板和類模板的補充。這章的主要內容包括 非型別的類模板引數。非型別的函式模板引數。非型別模板引數的限制。在具體介紹以前有比較說明一下什麼是非型別的模板引數。在前面簡單介紹函式模板和類模板的時候,我們都再三說明,模...
C 非型別模板引數
對於函式模板與類模板,模板引數並不侷限於型別,普通值也可以作為模板引數。在基於型別引數的模板中,你定義了一些具體的細節來加以確定 直到 被呼叫時這些細節才被真正的確定。但是在這裡,我們面對的是這些細節是值,而不是型別,當要使用基於值的模板時,必須顯式地指定這些值,才能夠對模板進行例項化。在上篇文章 ...
C 非型別模板引數
對 於函式模板與類模板,模板引數並不侷限於型別,普通值也可以作為模板引數。在基於型別引數的模板中,你定義了一些具體的細節來加以確定 直到 被調 用時這些細節才被真正的確定。但是在這裡,我們面對的是這些細節是值,而不是型別,當要使用基於值的模板時,必須顯式地指定這些值,才能夠對模板進行例項 化。在上篇...