【问题标题】:Understanding how std::forward overloads work了解 std::forward 重载如何工作
【发布时间】:2021-01-18 11:15:29
【问题描述】:

我想再次确认我对前向重载的工作原理有正确的理解

template< class T >
constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept;

template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;

如果我们用一些局部变量n 调用转发,比如int,重载将被指定为

  constexpr int&& forward( int& t ) noexcept;   
  constexpr int&& forward( int&& t ) noexcept;

所以我们的案例将选择第一个。如果我们只使用4 调用转发,将指定相同的重载,但将选择第二个版本。所以第一次重载总是捕获所有左值,其次是所有右值。对吗?

【问题讨论】:

标签: c++ c++11 templates c++14 forward


【解决方案1】:

是的。几乎。你不能只打电话给forward

如果您使用局部变量 n 调用 foward,例如 int

int n;
forward(n);

你得到一个编译错误。如果你打电话给forward&lt;int&gt;

int n;
forward<int>(n);

你得到两个重载候选:

constexpr int&& forward<int>(int& t)noexcept;
constexpr int&& forward<int>(int&& t)noexcept;

然后正常的重载决议运行,并选择第一个。

如果我们这样做

forward(4);

再次,编译错误,因为T无法推断,但如果我们这样做

forward<int>(4);

两个重载之间选择:

constexpr int&& forward<int>(int& t)noexcept;
constexpr int&& forward<int>(int&& t)noexcept;

其中第二个被选中。

当我们这样做时,事情会变得更有趣

int n;
forward<int&>(n);

我们得到

constexpr int& forward<int&>(int& t)noexcept;
constexpr int& forward<int&>(int&& t)noexcept;

返回值从int&amp;&amp; 变为int&amp;,但参数不变。

参数上的删除引用都阻止扣除模板参数,并确保引用折叠永远不会将它们变成左值引用。

所以第一个总是左值引用,第二个总是右值引用。

但要明确一点,您不能只调用 forward - 对于某些类型 T,您必须调用 forward&lt;T&gt;,而该类型 T 会改变重载的样子。在所有(几乎?)forward 的合理使用中,这并不重要,但不合理的使用可能会产生影响。

struct unreasonable {
  operator int&&()&;
};
unreasonable r;
forward<int>(r);

这将选择第二个重载。

【讨论】:

  • 感谢您的解释。我也检查过,如果调用 forward(8);但是你能解释一下你不合理的例子吗? Whta 是运算符 int&&()&; 中的最后一个 &?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 2015-11-30
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 2017-07-25
  • 2016-08-22
相关资源
最近更新 更多