2013-10-11 39 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

相关问题