【问题标题】:Can a forwarding reference be aliased with an alias template?转发引用可以用别名模板来别名吗?
【发布时间】:2015-04-25 16:35:05
【问题描述】:

这是我之前问题的延续:

Can an identity alias template be a forwarding reference?

以下代码似乎在 Clang 3.7.0 (demo) 和 GCC 6.0.0 (demo) 中都有效:

template <class T>
using forwarding_reference = T&&;

template <class T>
void foo(forwarding_reference<T>) {}

int main()
{
  int i{};
  foo(i);
  foo(1);
}

编译器是否有权将别名模板替换为转发引用,这可能是一种奇特的编写方式?

【问题讨论】:

  • 这不是完全相同的问题和完全相同的答案吗?
  • @Barry 这不是重复的。
  • @Barry 我不想更新已经回答的问题,认为这会让读者感到困惑
  • clang++3.5 顺便拒绝了这个程序。我记得不久前在 g++ 和 clang++ 中尝试过这个,并且对它在 clang 中不起作用感到失望。这似乎是隐藏T&amp;&amp; 实现细节同时提高可读性的好方法。查找提及类似问题的 clang 错误报告以及是否有一些讨论可能会很有趣。

标签: c++ templates alias c++14 forwarding-reference


【解决方案1】:

这确实符合标准。 §14.5.7/2:

template-id 指代一个别名模板的特化时, 相当于通过替换得到的关联类型 它的 template-argumentstype-id 中的 template-parameters 别名模板。

现在,考虑在模板参数推导期间,仅检查参数的类型(就模板参数而言) - §14.8.2.1/1:

模板参数推导是通过比较每个函数来完成的 模板参数类型(称之为P 调用的相应参数(称为A),如下所述。

根据第一个引号,参数的类型,即forwarding_reference&lt;T&gt;,等价于T&amp;&amp;。因此PT&amp;&amp; 并且在扣除上没有区别。

委员会在一份关于这种确切情况的缺陷报告中也得出了同样的结论,#1700

因为函数参数的类型都是一样的,不管 无论是直接写的还是通过别名模板写的,都必须扣除 两种情况下的处理方式相同。

【讨论】:

  • 谢谢,那么identity&lt;T&gt;&amp;&amp;(来自上一个问题)不应该也可以工作吗?我们首先将别名模板解析为T&amp;&amp;,然后进行模板参数推导。或者Angew's reasoning 是否正确,有一个额外的规则需要完全T&amp;&amp; 语法(无论在哪里)将其视为转发参考?
  • 两个编译器都声称void foo(identity&lt;T&gt;&amp;&amp;); 重新定义了void foo(forwarding_reference&lt;T&gt;);
  • @MarcAndreson 我认为 Angew 是不正确的,因为 P 在 14.8.2.1/1 中被定义为 "每个函数模板参数类型(称为 P)" .它已经是类型了,所以他的论点——identity&lt;T&gt;是模板参数的类型,但它本身不是模板参数”——似乎是错误的。跨度>
  • @MarcAndreson(如果你愿意,我可以在你之前的问题线程中发布另一个答案。我非常相信identity&lt;T&gt;&amp;&amp; 应该可以很好地进行演绎。
  • 是的,请随时添加您的答案。我会很感激的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 2011-11-04
  • 1970-01-01
  • 2021-12-18
  • 2015-05-15
相关资源
最近更新 更多