[英]Partial template specialization type collapsing rules
抱歉,缺少更好的標題。
在嘗試實現自己的std::move
版本並理解它的簡單性時,我仍然對C ++如何對待部分模板專業化感到困惑。 我知道它們是如何工作的,但是我發現有些規則很奇怪,我想知道其背后的原因。
template <typename T>
struct BaseType {
using Type = T;
};
template <typename T>
struct BaseType<T *> {
using Type = T;
};
template <typename T>
struct BaseType<T &> {
using Type = T;
};
using int_ptr = int *;
using int_ref = int &;
// A and B are now both of type int
BaseType<int_ptr>::Type A = 5;
BaseType<int_ref>::Type B = 5;
如果沒有RemoveReference
部分專業知識,則T
始終為T
:如果我給出一個int &
並且在整個模板中仍為int &
。
但是,部分專用模板似乎折疊了引用和指針:如果我給出了int &
或int *
,並且這些類型與專用模板中的類型匹配,則T
僅為int
。
此功能非常棒且有用,但是我很好奇,我想知道這個不太明顯的怪癖背后的官方推理/規則。
如果您的模板模式將T&
與int&
匹配,則T&
為int&
,這意味着T
為int
。
專業化中的類型T
僅與主要模板中的T
有關,因為它用於對第一個參數進行模式匹配。
在專業領域中,用X
或U
代替T
可能會減少您的困惑。 重用變量名可能會造成混淆。
template <typename T>
struct RemoveReference {
using Type = T;
};
template <typename X>
struct RemoveReference<X &> {
using Type = X;
};
和X&
匹配T
如果X&
為T
,並且T
ia為int&
,則X
為int
。
標准為什么這么說?
假設我們看到了另一種模板專業化:
template<class T>
struct Bob;
template<class E, class A>
struct Bob<std::vector<E,A>>{
// what should E and A be here?
};
部分專業化的行為與功能模板非常相似:事實上,重載功能模板常常被誤認為是對其進行部分專業化(這是不允許的)。 特定
template<class T>
void value_assign(T *t) { *t=T(); }
那么顯然T
必須是沒有(最外)指針狀態的參數類型的版本,因為我們需要該類型來計算通過指針分配的值。 我們當然通常不會寫value_assign<int>(&i);
調用此類型的函數,因為可以推導參數。
在這種情況下:
template<class T,class U>
void accept_pair(std::pair<T,U>);
請注意,模板參數的數量大於作為輸入的“提供”類型的數量(即,大於用於推導的參數類型的數量):復雜類型可以提供“一種以上的價值”的信息。
所有這些看起來與類模板非常不同,在類模板中 ,必須顯式地指定類型( 從C ++ 17開始有時是正確的 ),並且在模板中逐字使用它們(如您所說)。
但是,請再次考慮部分專業化:
template<class>
struct A; // undefined
template<class T>
struct A<T*> { /* ... */ }; // #1
template<class T,class U>
struct A<std::pair<T,U>> { /* ... */ }; // #2
它們分別與(不相關的)功能模板value_assign
和accept_pair
完全同構。 我們必須編寫例如A<int*>
來使用#1; 但這僅類似於調用value_assign(&i)
:特別是,模板參數仍然被推導 ,只是這次是從顯式指定的類型int*
而不是從表達式&i
的類型推導的 。 (因為即使提供顯式模板參數也需要推導,所以部分專業化必須支持推導其模板參數。)
#2再次說明的想法,類型的數量在這個過程中不守恆:這應該有助於打破的虛假印象的“ 模板參數”應繼續提及“ 所提供的類型”。 因此,部分專業化不僅僅要求(通常是無限制的)模板參數集:它們還會解釋它們。
另一個相似之處是:同一類模板的多個部分專業化選項之間的選擇與重載時丟棄不那么特定的功能模板的選擇完全相同 。 (但是,由於在部分專業化的情況下不會發生重載解決方案,因此該過程必須除去那里的所有候選對象,但所有候選對象除外。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.