简体   繁体   English

在c ++中使用std :: forward

[英]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::stringconst 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 ,即TT&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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM