如何解决了解 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 举报,一经查实,本站将立刻删除。