微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

了解 std::forward 重载的工作原理

如何解决了解 std::forward 重载的工作原理

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

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 调用 forward,假设它是 int,重载将被指定为

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

所以我们会选择第一个。如果我们仅使用 4 调用 forward,则将指定相同的重载,但将选择第二个版本。所以第一个重载总是捕获所有的左值,然后是所有的右值。正确吗?

解决方法

是的。几乎。您不能只调用 forward

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

int n;
forward(n);

你得到一个编译错误。如果您调用 forward<int>

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&& 变为 int&,但参数没有变化。

参数上的删除引用既阻止了模板参数的推导,又确保引用折叠永远不会将它们变成左值引用。

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

但要明确的是,您不能只调用 forward -- 您必须为某种类型 forward<T> 调用 T,而该类型 T 会改变重载的内容看起来像。在所有(几乎?)合理使用 forward 中,这并不重要,但不合理使用可能会产生影响。

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

这将选择第二个重载。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。