【问题标题】:Returning a forwarded reference返回转发的引用
【发布时间】:2014-02-22 13:12:51
【问题描述】:

我想构建一个最大值函数,将较大的值转发给结果,同时保持引用的类型(右值或左值)。

#include <utility>

template<typename T>
constexpr T&& mmax(T&& left, T&& right) {
    return left > right ? std::forward<T>(left) : std::forward<T>(right);
}

int main() {
    mmax(1, 2);
}

但是,这给了我

max.cc: In instantiation of 'constexpr T&& mmax(T&&, T&&) [with T = int]':
max.cc:9:14:   required from here
max.cc:5:72: warning: returning reference to temporary [-Wreturn-local-addr]
     return left > right ? std::forward<T>(left) : std::forward<T>(right);

这是为什么呢?我正在使用带有 -std=c++11 的 GCC 4.8.2。

编辑:clang++不会发生这种情况。

【问题讨论】:

  • return std::forward&lt;T&gt;(left &gt; right ? left : right) 怎么样?
  • 你用的是什么编译器?我没有使用 Apple LLVM 5.0 的警告
  • 这很奇怪,无论如何 - 你不能真正拥有 多个 参数的通用参考。
  • @kerreksb 当然可以,只是没那么有用!
  • @trion:推导一个参数并强制另一个参数具有相同类型的标准方法是使第二种类型不可推导,如下所示:template &lt;typename T&gt; void foo(T &amp;&amp; a1, typename std::common_type&lt;T&gt;::type a2) 现在a1 受通用约束参考,a2 必须能够匹配。

标签: c++ c++11


【解决方案1】:

由于 C++ 11 5.16/4 中有关条件运算符的规则,您的原始代码应该可以工作:

如果第二个和第三个操作数是相同值类别的glvalues并且具有相同的类型,则结果是该类型和值类别

forward&lt;T&gt;(left)forward&lt;T&gt;(right)这两个表达式要么都是左值,要么都是xvalue,所以它们总是glvalues,它们都是T类型,所以规则适用,条件表达式的类型应该是相同的类型和值类别。

但是,作为潜在编译器错误的解决方法,您可以使用以下表达式,这样可以避免弄清楚条件表达式的类型和值类别(这似乎是错误所在):

return std::forward<T>(left > right ? left : right);

【讨论】:

  • 上面的危险是,如果转换已经完成,你现在默默地返回一个对 trmporary 的引用。如果您使用T&amp;&amp;,请考虑返回T,它也可以延长引用生命周期。
  • @Yakk:嗯,很难争论不合格的编译器会做什么。我们知道leftright 都是引用,所以不应该有任何临时的,但谁知道呢?
  • @Kerrek:为什么不能有临时工?只有非常量左值引用不会绑定到临时对象,并且此函数同时接受 const 左值引用和右值引用。
  • @BenVoigt:但这些不是函数创建的临时变量。他们是调用者的责任。
  • 检查 auto&amp;&amp; x=mmax(exp1,exp2); 如果 exp1 或 2 是临时的,事情进展不顺利。您很少想要返回 T&amp;&amp; - 返回 T 并且一切顺利。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-24
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 2018-08-08
  • 1970-01-01
相关资源
最近更新 更多