2014-09-30 68 views
0

我真的很模糊。 如果我有一個模板類,我把它作爲一個參數傳遞給函數,考慮以下因素:模板功能和類

template <class T> class Class 
{ 

}; 

所以我想打一個函數,類作爲參數,那麼爲什麼以下不會足夠:

void func(Class<T> obj) 
{ 

} 

,我必須做:

template <class T> void func(Class<T> obj) 
{ 

} 

也是,說我拿2個模板類的2個參數,考慮以下因素:

template <class T> class ClassA 
{ 

}; 
template <class T> class ClassB 
{ 

}; 

,我有一個函數,類型ClassA和ClassB的,就是寫作的區別的2個參數:

template <class T> void func(ClassA<T> obj1, ClassB<T> obj2) 
{ 

} 

template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2) 
{ 

} 

,因爲這兩個作品。

+0

'模板'中的'ClassB'只是一個名稱,並不是指您的實際'template class ClassB' – 2014-09-30 16:29:22

+0

@PiotrS。這是什麼意思,這只是一個名字,思維解釋? – 2014-09-30 16:31:05

+1

不要將模板視爲泛型(如在C#中)。它們更像是編譯器的替換指令:用指定的任何內容替換'T',比如'int'。 – 2014-09-30 16:49:02

回答

3

不要被class關鍵字混淆class ClassB語法模板參數列表。也就是說,那裏的class關鍵字並不指示實際的類別(甚至沒有給定名稱的類別),而是它是在模板參數列表中將被推導或指定的類型的名稱。另外,(我喜歡),您可以使用typename關鍵字,它更好地表達其含義:

即:

template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2) 

等於:

template <typename T, typename ClassB> void func(ClassA<T> obj1, ClassB obj2) 

內的ClassBfunc範圍會影響class ClassB聲明。在功能範圍內,這是在模板參數列表中推導或指定的類型的名稱。也就是說,它可以是從字面上任何東西:

func(ClassA<int>{}, 123); // ClassB is now deduced to be int 
func(ClassA<int>{}, 3.14); // ClassB is now deduced to be double 
func(ClassA<int>{}, 'A'); // ClassB is now deduced to be char 
func<int, long long>(ClassA<int>{}, 5); // ClassB is specified to be long long 

和實例示出了遮蔽:

template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2) 
{ 
    ClassB a; // a has the deduced or specified type 
    ::ClassB<int> b; // b has the true ClassB<int> type 
}  

最後,上述聲明和下方的一個之間的差值:

template <class T> void func(ClassA<T> obj1, ClassB<T> obj2) 

是在後一種情況下func接受ClassA實例和ClassB實例具有相同的類型參數,而第一個正如所說的,聲明可以匹配任何類型作爲第二個聲明。換句話說,在第一個例子中,第一個參數類型的模板參數推導機制被限制爲僅在ClassA<T>聲明中推導出T類型,並且在推導第二個參數類型時不受任何限制。

+0

真的幫助我理解,謝謝你的描述性答案! – 2014-09-30 17:07:43

1

類模板不是類,函數模板也不是函數,它們只是用於生成它們的模板。

因此,難怪你不能在需要類型相應功能的情況下使用模板。

模板參數的名稱與其作用域外的函數參數的名稱具有相同的重要性:
沒有任何。在他們的範圍內,他們自然而然地從外部範圍映射名稱。

因此,令牌T可能並不表示您試圖聲明(以及另外定義)您的函數的任何內容。
ClassB以模板名稱作爲template-argument-name,表示teplate-argument而不是某個可能碰巧存在的外層作用域類。

+0

'T'不是預處理令牌。 – 0x499602D2 2014-09-30 16:45:44

+0

這也是一個預處理令牌,但這不是我們感興趣的:我們只對ttranslation的後期階段感興趣,您對此非常感興趣。 – Deduplicator 2014-09-30 16:48:25