我正在撰寫一個涉及類模板專業化的示例,其中我注意到該標準允許兩種不同的語法用于資料成員的專業化,如下所示:
template<typename T >
struct C {
static int x;
};
template<>
struct C<bool> {
static int x;
};
//here we cannot write prefix template<>
int C<bool>::x = 0;
從上面的例子可以看出,我們不允許寫前綴template<>來定義靜態資料成員x。我理解這一點,對上面的例子沒有問題。但是當我將示例修改為如下所示時,我驚訝地發現我們被允許/要求撰寫template用于定義靜態資料成員的前綴x:
template<typename T >
struct C {
static int x;
};
template<> //here why is the use of prefix template<> allowed/required? Why standard mandates that we cannot omit this prefix template<> here but in the previous example we can omit it
int C<bool>::x = 0;
從上面的修改示例中可以看出,我們需要使用前綴template<>來定義相同的靜態資料成員x。我的問題是x,為什么在上述兩個示例中定義相同資料成員的語法存在差異。這就是標準要求template<>在第二個示例中使用前綴的原因。為什么我們不能像第一個示例一樣在第二個示例中省略該前綴。在第二個示例中使用前綴是否template<>有助于解決某些問題(例如一些歧義或其他問題)。
PS:請注意,我的問題不是關于標準中的哪個陳述句允許這種用法(因為我已經知道使用下面給出的來自 cppreference 的參考陳述句),而是關于允許這兩種語法的基本原理(一種使用template<>,一種不使用) )。
我還遇到了以下內容以及上述鏈接中給出的代碼示例,這些示例解釋了如何允許這樣做:
在類的主體之外定義顯式特化的類模板的成員時,不使用語法 template<>,除非它是顯式特化的成員類模板的成員,該模板被特化為類模板,否則,語法將要求此類定義以嵌套模板所需的模板開頭。
上面參考的陳述與那里給出的示例一起解釋了標準如何在我的問題中允許上面給出的示例。但我正在尋找為什么template<>第二個示例中的標準規定前綴的原因。為什么標準不允許template<>在第二個示例中省略前綴,如示例 1。
uj5u.com熱心網友回復:
它們不是同一事物的不同語法,它們是不同事物的不同語法。
第一個專門化整個結構,包括它的所有成員。
也就是說,C<bool>::x結構特化已經隱含了特化,并且不允許進行兩次特化。
int C<bool>::x = 0;是該專業化中靜態成員的常規定義。
第二個只專門化成員,而不是結構,并同時定義它。
uj5u.com熱心網友回復:
首先
template<typename T >
struct C {
static int x;
};
// This is the template specialisation for bool and all struct members
template<>
struct C<bool> {
static int x;
};
// This is the extraneous template specialisation for bool
// and the single struct member, already specialized above - error
// template<>
// int C<bool>::x = 0;
修改后的第一個示例
template<typename T >
struct C {
static int x;
};
// This is the template specialisation for bool and the single struct member
template<>
int C<bool>::x = 0;
// This is the extraneous template specialisation for bool
// and all struct members, one of them is already specialized above - error
// template<>
// struct C<bool> {
// static int x;
// };
第二
template<typename T >
struct C {
static int x;
};
// This is the unique template specialisation for bool - ok
template<>
int C<bool>::x = 0;
另一個例子
template<typename T >
struct C {
static int x;
};
// This is the template specialisation for bool
template<>
struct C<bool> {
static int x;
};
// This is another template socialisation for int - ok
template<>
int C<int>::x = 0;
uj5u.com熱心網友回復:
類模板的顯式特化宣告不是模板宣告。[來源]。這意味著當我們為類模板提供顯式特化時,它的行為就像一個普通的類。
現在我們可以將其應用于所給出的示例。
示例 1
template<typename T >
struct C {
static int x;
};
//this is an specialization and so we must use template<> prefix
template<>
struct C<bool> {
static int x;
};
//this is just ordinary out of class definition of data member `x`. That is, this is not a specialization and so we don't need the prefix template<>
int C<bool>::x = 0;
在上面的例子中,首先我們為bool類模板C本身提供了一個明確的特化,它的行為就像一個普通的類(在某種意義上它不是一個模板宣告)。這里template<>需要前綴,因為我們提供了一個專業化。接下來,我們為我們提供的專業化的靜態資料成員提供一個普通的類外定義。x但是這里我們不需要template<>前綴,因為這不是專業化的。這只是靜態資料成員的普通類外定義。
示例 2
template<typename T >
struct C {
static int x;
};
template<> // needed because this is not an ordinary out-of-class definition of data member x. Instead this is a specialization
int C<bool>::x = 0;
在上面的示例中,我們沒有為類模板 C 提供任何明確的特化。相反,我們直接為靜態資料成員提供了特化x。這意味著與示例 1 不同的是,這里我們沒有提供靜態資料成員的類外定義,而是提供了一個特化。所以在這種情況下,我們需要template<>前綴。
TLDR
在示例 1int C<bool>::x = 0;中,它只是靜態資料成員的普通類外定義,x而不是特化,因此我們不需要前綴template<>。相反,在示例 2template<> int C<bool>::x = 0;中是靜態資料成員x的特化,而不是普通的類外定義。所以在這種情況下(示例 2)template<>需要前綴。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/473682.html
