非型別模板引數的限制

2021-08-08 18:16:09 字數 2420 閱讀 1783

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 guide

static inline與內部、外部鏈結物件

模板非型別形參的詳細闡述

非型別模板引數

這是 c templates 第四章的學習筆記。這一章和下一章可以看作是對前面介紹的函式模板和類模板的補充。這章的主要內容包括 非型別的類模板引數。非型別的函式模板引數。非型別模板引數的限制。在具體介紹以前有比較說明一下什麼是非型別的模板引數。在前面簡單介紹函式模板和類模板的時候,我們都再三說明,模...

C 非型別模板引數

對於函式模板與類模板,模板引數並不侷限於型別,普通值也可以作為模板引數。在基於型別引數的模板中,你定義了一些具體的細節來加以確定 直到 被呼叫時這些細節才被真正的確定。但是在這裡,我們面對的是這些細節是值,而不是型別,當要使用基於值的模板時,必須顯式地指定這些值,才能夠對模板進行例項化。在上篇文章 ...

C 非型別模板引數

對 於函式模板與類模板,模板引數並不侷限於型別,普通值也可以作為模板引數。在基於型別引數的模板中,你定義了一些具體的細節來加以確定 直到 被調 用時這些細節才被真正的確定。但是在這裡,我們面對的是這些細節是值,而不是型別,當要使用基於值的模板時,必須顯式地指定這些值,才能夠對模板進行例項 化。在上篇...