4

可能重複:
Priority when choosing overloaded template functions in C++C++函數重載解析關於模板類型和類層次結構

模板化的功能讓我有方便的多種類型的操作:

template<typename T> void destroy(T* obj) { 
    delete obj; 
} 

但是在某些時候,我想對類層次結構進行一些專門化處理Y:

class Base { virtual void doSomething(); }; 
class Derived : public Base {}; 
void destroy(Base* obj) { 
    obj->doSomething(); 
    delete obj; 
} 

,如果我一通確切類型Base*預期的專業化功能也被調用,但是重載解析規則似乎更喜歡的,而不是執行靜態起來投通用模板版本,如果我一通Derived*void detroy()

當然,我可以爲所有可能的派生類型製作所有的重載函數,但它不易維護。

我使用的是Visual C++ 2008,有沒有解決上述問題的方法?

+0

剛剛發現堆棧溢出同樣問題的一個簡潔的答案:[優先選擇C++中的重載模板函數](http://stackoverflow.com/questions/1332678/priority-when-choosing-overloaded-template-functions -in-c) – 2010-09-08 08:46:57

+0

但是你的破壞函數有問題。它將被調用一維數組類型,你可以登陸做'刪除'而不是'delete []'這是未定義的行爲。 – Chubsdad 2010-09-08 09:02:49

+0

Op承認這個Q應該作爲一個副本來關閉。 – 2011-12-04 06:34:47

回答

0

有沒有這樣的事情的Visual C++ 2009年

您可以用另一個模板專門的功能和使用SFINAE只匹配基地的亞型。但我不知道編譯器會喜歡第二個版本的任何理由,通常專業化必須以某種方式「更好」才能被選中。

或者,您可以使用SFINAE和助手traits類來防止泛型版本與Base的子類匹配。如果你需要一個這樣的例子,問。

當然,您的專業化只能用於可見的地方。模板化函數總是內聯的,它們和專業化需要位於調用者包含的頭文件中。

5

所有的事情都是相同的,重載決議偏好非模板功能的功能模板。但是,在這種情況下,所有的事情都是不平等的。爲了匹配你的過載Base*,派生到基地指針的轉換是必要的;不需要轉換來匹配函數模板。因此,功能模板被選爲Derived*

在調用函數之前,「簡單」,儘管可能容易出錯,但解決方案是將Derived*強制轉換爲Base*

至少在理論上,您可以按照Ben的建議採用SFINAE方法,但是您必須明確地禁用您爲其提供專業化的任何類型的通用函數模板,否則最終會出現超載歧義。這比明確的轉換方法更加不可維護且容易出錯。 (雖然,這裏的某個人可能會知道另一種解決超負荷歧義的方法;但是我肯定有興趣知道是否有)。