2017-04-06 88 views
4

以下代碼使用g ++編譯,但無法使用clang進行編譯。類模板中的Typedef評估

struct X; 

template <typename T> 
struct Traits 
{ 
    typedef typename Traits<T>::Container Container; 
}; 

template <> 
struct Traits<X> 
{ 
    typedef std::vector<X *> Container; 
}; 

int main() 
{ 
    Traits<X>::Container container; 
    return EXIT_SUCCESS; 
} 

鐺錯誤消息:

main.cpp:9:30: error: no type named 'Container' in 'Traits<T>' 

編譯器應該不會與實際類型替換模板參數評估的typedef?哪個編譯器是正確的?

鐺:http://coliru.stacked-crooked.com/a/fef7725827074e4f

GCC:http://coliru.stacked-crooked.com/a/79e17031fcabcd83

+4

'的typedef typename的性狀 ::集裝箱貨櫃;'是一個無限遞歸的typedef ... – cdhowie

+0

我猜想,因爲性狀是一個從屬名稱,應該實例化過程中評估。但我無法用任何相關的標準報價來證明它。 – SergeyA

+0

@cdhowie,我不確定它是否會,甚至會這樣,編譯器可能會抱怨最大模板深度,而不是缺少類型? – SergeyA

回答

4
template <typename T> 
struct Traits { 
    typedef typename Traits<T>::Container Container; 
}; 

這是病態形成,沒有診斷需要。沒有T這樣的上述(主要)專業化可能會導致有效的代碼。

另一個專業化的存在沒有區別。編譯器可以自由地做任何事情,包括給出一個虛假的錯誤消息。編譯它是免費的。只有在程序的其他地方有一個名爲foo的變量,或者如果月亮是新的,它纔會自由產生錯誤。一些如果這些是實施質量差。

實際上,這意味着編譯器可以自由地假定主要特化對於某些類型T(即,其中沒有無限遞歸)是有效的,並且在相對不相關的代碼中出現,因爲它做出了這個假設。