[英]Template Non-Type argument, C++11, restriction for string literals
模板非類型參數的限制規則說:
非類型非模板模板參數的模板參數應為以下之一:
- 對於整數或枚舉類型的非類型模板參數,模板參數類型的轉換常量表達式(5.19); 要么
- 非類型模板參數的名稱; 要么
- 一個常量表達式(5.19),用於指定具有靜態存儲持續時間和外部或內部鏈接的對象的地址,或具有外部或內部鏈接的函數,包括函數模板和函數模板ID,但不包括非靜態類成員,表達(忽略括號)as&id-expression,除非如果名稱引用函數或數組,則可以省略&,如果相應的template-parameter是引用,則省略; 要么
- 一個常量表達式,其值為空指針值(4.10); 要么
- 一個常量表達式,其值為null成員指針值(4.11); 要么
- 指向成員的指針,如5.3.1中所述。
2 [ 注意:字符串文字(2.14.5)不滿足任何這些類別的要求,因此不是可接受的模板參數。
[ Example:
template<class T, const char* p> class X {
/ ... /
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK
—end example ] —end note ]
那么為什么字符串文字不能用作非類型參數的參數?
const char arr[5] = "1234";
arr具有相同的類型const char [5]
"1234";
arr具有外部鏈接,這就是為什么允許在c ++ 11標准之前使用arr作為非類型模板參數。
但是現在指向具有內部鏈接(靜態存儲)的對象的指針也允許用作非類型模板參數,而字符串文字具有內部鏈接。
從你的問題來看,最接近字符串文字的是:
一個常量表達式(5.19),用於指定具有靜態存儲持續時間和外部或內部鏈接的對象的地址
字符串文字既沒有外部鏈接也沒有內部鏈接,因此不允許使用它們。
如果你有多個翻譯單元,每個翻譯單元都包含const char arr[5];
的定義const char arr[5];
通過內部鏈接,那些都是不同的對象,具有不同的地址,但在單個翻譯單元中, arr == arr
,始終。 實現找到了如何使模板參數工作。
如果您有多個翻譯單元,每個單元包含"1234"
, 則不保證這些單元具有不同的地址。 然而,即使在單個翻譯單元中,也不能保證它們具有相同的地址。
如果"1234" != "1234"
,則引用模板S<"1234">
沒有意義:每次都要引用不同的模板實例化。
如果"1234" == "1234"
,則實現變得復雜以確保S<"1234">
在每個翻譯單元中是相同的類型。
真的很有趣,以下代碼是有效的C ++ 11,但字符串文字將無法正常工作。 對於C ++ 14,您甚至可以刪除static_cast。
#include <iostream>
static constexpr const char s1[] = "Hello World!";
static const char s2[] = __DATE__ " " __TIME__;
template< const char* STR > struct X {X() {std::cout << STR << std::endl;}};
X< s1 > x1;
X< static_cast<const char*>(s2) > x2;
int main() {}
即使今天的C ++編譯器不接受字符串文字,在某些情況下允許這樣做會非常方便。
接受臨時類實例化的地址作為NT模板參數將進入類似的方向:
#include <iostream>
struct S {int s;};
static constexpr const S s1{123};
static const S s2{999};
template< const S* _S > struct X {X() {std::cout << _S->s << std::endl;}};
X< &s1 > x1;
X< &s2 > x2;
//NOT OK: X< (&S{1}) > x3;
int main() {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.