[英]Use of std::forward in c++
I have come across a code, where std::forward
is used. 我遇到过一个代码,其中使用了
std::forward
。 I have googled about it for a longtime and not able to understand its real purpose and use. 我已经搜索了很长时间,并且无法理解它的真实目的和用途。
I have seen similar threads in stackoverflow, but still not clear. 我在stackoverflow中看到了类似的线程,但仍然不清楚。 Can somebody explain it with a simple example?
有人可以用一个简单的例子解释一下吗?
PS: I have gone through this page , but still not able to appreciate its use. PS:我已经浏览了这个页面 ,但仍然无法欣赏它的使用。 Please do not flag this question duplicate and rather try to help me out.
请不要将此问题标记为重复,而是尝试帮助我。
As the page you linked poses it: 当你链接的页面构成它:
This is a helper function to allow perfect forwarding of arguments taken as rvalue references to deduced types, preserving any potential move semantics involved.
这是一个辅助函数,可以完美地转发作为对推导类型的rvalue引用的参数,保留所涉及的任何潜在的移动语义。
When you have a named value , as in 当你有一个命名值时 ,如
void f1(int& namedValue){
...
}
or in 或者在
void f2(int&& namedValue){
...
}
it evaluates , no matter what, to an lvalue
. 无论如何,它都会评估
lvalue
。
One more step. 更进一步。 Suppose you have a template function
假设你有一个模板功能
template <typename T>
void f(T&& namedValue){
...
}
such function can either be called with an lvalue or with an rvalue; 这样的函数可以用左值或右值调用; however, no matter what, namedValue evaluates to an
lvalue
. 但是,无论如何,namedValue都会评估为
lvalue
。
Now suppose you have two overloads of an helper function 现在假设您有两个辅助函数重载
void helper(int& i){
...
}
void helper(int&& i){
...
}
calling helper
from inside f
从
f
里面调用helper
template <typename T>
void f(T&& namedValue){
helper(namedValue);
}
will invariably call the first overload for helper
, since namedValue
is, well, a named value which, naturally, evaluates to an lvalue
. 将总是调用
helper
的第一个重载,因为namedValue
是一个命名值 ,当然,它会计算为lvalue
。
In order to get the second version called when appropriate (ie when f
has been invoked with a rvalue parameter), you write 为了在适当的时候调用第二个版本(即当用rvalue参数调用
f
时),你写
template <typename T>
void f(T&& namedValue){
helper( std::forward<T>(namedValue) );
}
All of this is expressed much concisely in the documentation by the following 以下所有这些都在文档中非常简明扼要地表达出来
The need for this function stems from the fact that all named values (such as function parameters) always evaluate as lvalues (even those declared as rvalue references), and this poses difficulties in preserving potential move semantics on template functions that forward arguments to other functions.
对这个函数的需求源于这样一个事实,即所有命名值(例如函数参数)总是作为左值(甚至是那些被声明为右值引用的值)进行评估,这在保留模板函数上的潜在移动语义方面存在困难,模板函数将参数转发给其他函数。
Each expression is in exactly one of the following two value categories: lvalue or rvalue. 每个表达式恰好是以下两个值类别之一:左值或右值。
Normally if you call a function like: 通常,如果你调用如下函数:
template<typename T>
void f(T t);
template<typename T>
void g(T t)
{
f(t);
}
The value category of the argument to g
is lost between the call to g and f, because named parameters, like local variables, are always lvalues. g
的参数的值类别在调用g和f之间丢失,因为命名参数(如局部变量)总是lvalues。
By using std::forward
and adjusting the parameter to a "universal reference" that uses reference collapsing you can preserve the value category: 通过使用
std::forward
并将参数调整为使用引用折叠的“通用引用”,您可以保留值类别:
template<typename T>
void f(T&& t);
template<typename T>
void g(T&& t)
{
f(forward<T>(t));
}
That's why it's called "forward", because you are "forwarding" the value category on, rather than losing it. 这就是为什么它被称为“前进”,因为你正在“转发”价值类别,而不是失去它。
So in the example if you call g
with an rvalue, then f will be called with an rvalue - rather than an lvalue. 因此,在示例中,如果使用rvalue调用
g
,则将使用rvalue调用f - 而不是左值。
It is used to preserve the exact type of an argument in templates when passing it to another function. 它用于在将模板传递给另一个函数时保留模板中参数的确切类型。 For example:
例如:
template<class T>
void wrapper(T&& arg)
{
foo(std::forward<T>(arg)); // Forward a single argument.
}
This works as follows: 其工作原理如下:
If the function wrapper
gets a std::string
or const std::string&
, then foo
is called as if arg
has type of const std::string&
. 如果函数
wrapper
获取std::string
或const std::string&
,则调用foo
就好像arg
具有const std::string&
。
If the function wrapper
gets a std::string&
, then foo
is called as if arg
has type of std::string&
. 如果函数
wrapper
获取std::string&
,则调用foo
就好像arg
具有std::string&
类型一样。
If the function wrapper
gets a std::string&&
, then foo
is called as if arg
has type of std::string&&
. 如果函数
wrapper
获取std::string&&
,则调用foo
就好像arg
具有std::string&&
类型。
The problem that std::forward
solves is that by the usual rules the type of arg
within function is std::string
even if we pass std::string&&
to wrapper
. std::forward
解决的问题是通过常规规则,函数中的arg
类型是std::string
即使我们将std::string&&
传递给wrapper
。 std::forward
allows to inject the actual type of T
, be it T
, T&
, const T&
or T&&
, to the call site. std::forward
允许向调用站点注入实际类型的T
,即T
, T&
, const T&
或T&&
。
It's basic use is you're in function g
that has been called like this: 它的基本用途是你在函数
g
中被称为这样:
g(T1 p1, T2 p2, /* ... */);
and you want to call function f
with exactly the same types: 并且您想要使用完全相同的类型调用函数
f
:
f(T1 p1, T2 p2, /* ... */);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.