2013-10-11 37 views
6

我們在follwing源代碼的編譯中觀察到的奇怪的行爲:作爲模板模板參數的C++ 11模板別名導致不同的類型?

template<template<class> class TT> struct X { }; 
template<class> struct Y { }; 
template<class T> using Z = Y<T>; 

int main() { 
    X<Y> y; 
    X<Z> z; 
    z = y; // it fails here 
} 

這是從C++ 11標準提案爲模板別名截取的略微變形例:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf(參見第4頁) 還要注意提案「聲明y和z是同一類型的。」因此,在我們的解釋中,應該可以從y分配(或複製構造)z。

但是,這段代碼不能用gcc 4.8.1和clang 3.3編譯。這是編譯器中的錯誤還是我們誤解了標準?

由於提前, craffael等人)

P.S.鐺鐺錯誤消息是:

error: no viable overloaded '=' 

note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'X<template Y>' to 'const X<template Z>' for 1st argument 
template<template<class> class TT> struct X { }; 

note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'X<template Y>' to 'X<template Z>' for 1st argument 
template<template<class> class TT> struct X { }; 
+0

'Y'和'Z'是不同的* template-names *,因此它們會產生與'X'不同的實例。見§14.5.7/ 1。 – Xeo

回答

8

目前的標準並沒有這麼說,但意圖是y和z具有相同的類型。這是一個開放的核心工作組問題:http://wg21.cmeerw.net/cwg/issue1286

+0

非常感謝,這確實是缺失的關鍵。我只是掃描標準的權利,並沒有真正發現我的代碼格式不正確的暗示。但是我注意到,提案中的例子稍微改變了Daniel Frey所建議的例子。這種暗示我的代碼可能是不健康的,但它沒有明確地說(這是我的解釋) 無論如何,我真的希望問題1286使它成爲下一個標準... – craffael

+0

+1有趣,所以我的答案*是*正確的,但是(希望)會改變。很高興知道! –

+1

在第1244期中,人們注意到沒有措辭支持該示例,因此核心工作組更新了該示例。然而,Gaby Dos Reis隨後評論說,其意圖的確是爲了讓原始示例保持良好形式,因此打開1286問題來更新規範文本(並將示例更改回來)。 – cmeerw

3

我覺得你是一個混淆類型和模板(或模板別名)。你有Y,這是一個模板和Z,這是另一個。如果你認爲Y == Z,你錯了。只有將它們轉換爲類型時,那些類型纔是相同的,例如, Y<int>是與Z<int>相同的類型。在您的例子:

template<class T> struct X { }; 

template<class> struct Y { }; 
template<class T> using Z = Y<T>; 

int main() { 
    X<Y<int>> y; 
    X<Z<int>> z; 
    z = y; // works 
} 

在你原來的代碼你提到他們X<Y>X<Z>,但Y是不一樣的Z,所以是X<Y>X<Z>不同的類型。

+0

我知道類型和模板是不一樣的,我完全同意你的例子應該編譯。然而,從標準來看,我的代碼是不合格的(參見cmeerw的答案)。 – craffael

相關問題