【问题标题】:C++11 template alias as template template argument leads to different type?C++11模板别名作为模板模板参数导致不同的类型?
【发布时间】:2016-06-01 02:17:21
【问题描述】:

我们在以下源代码的编译中观察到一个奇怪的行为:

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 等人;)

附: Clang 错误信息是:

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 { };

【问题讨论】:

  • YZ 是不同的 模板名称,因此它们会产生与 X 不同的实例化。见§14.5.7/1。

标签: c++ templates c++11 template-templates template-aliases


【解决方案1】:

目前的标准并没有这么说,但意图是 y 和 z 具有相同的类型。有一个开放的核心工作组问题:http://wg21.cmeerw.net/cwg/issue1286

【讨论】:

  • 非常感谢,这确实是缺少的关键。我只是在扫描标准权限,并没有真正找到我的代码格式错误的提示。然而,我注意到提案中的示例与 Daniel Frey 建议的示例略有不同。这种暗示我的代码可能格式不正确,但并没有说得那么明确(这是我的解释)无论如何我真的希望问题 1286 能成为下一个标准......
  • +1 很有趣,所以我的回答正确的,但这(希望)会改变。很高兴知道!
  • 在 issue 1244 中注意到没有支持该示例的措辞,因此核心工作组更新了该示例。然而,Gaby Dos Reis 随后评论说,其目的确实是为了使原始示例格式正确,因此打开了 issue 1286 以更新规范性文本(并将示例改回)。
  • 我希望在此之后他们能够做到f == g 给出int f(int x) { return g(x); }int g(int)
  • @R.MartinhoFernandes:这种“强制内联”会在复杂情况下改变语义,并会阻止与 ABI 兼容的重构。
【解决方案2】:

我认为您混淆了类型和模板(或模板别名)。你有Y,这是一个模板和Z,这是另一个模板。如果你认为Y == Z,那你就错了。仅当您将它们转换为类型时,那些 types 是相同的,例如Y&lt;int&gt;Z&lt;int&gt; 的类型相同。在您的示例中:

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&lt;Y&gt;X&lt;Z&gt; 来引用它们,但由于YZ 不同,因此X&lt;Y&gt;X&lt;Z&gt; 的类型也不同。

【讨论】:

  • 我知道类型和模板不一样,我完全同意您的示例应该编译。但是,从标准来看,我的代码是否格式错误似乎还不清楚(参见 cmeerw 的回答)。
猜你喜欢
  • 2018-08-26
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多