When not to use std::forward with r-values?

北城以北 提交于 2019-12-08 17:20:39

问题


What are the cases when std::forward is not needed? It is used to wrap inner function argument which is templated-rvalue (that is, it can be lvalue or named-rvalue). Like in:

template<class T>
void outer(T&& t) { 
    inner(std::forward<T>(t)); 
}

I am guessing one case is when inner function parameters are passed by value. Are there other cases? I've got this question when I was writing std::begin(std::forward<Ct>(ct)) where Ct is templated-rvalue-ref.

EDIT about possible duplicate

If I remember correctly, this is 3rd attempt to close this 4yr old question as duplicate by some newbie who don't understand the question.

"Advantages of using forward?" and "When not to use std::forward with r-values?" are very different questions. First is introduction into r-values for beginners and second is discussion of perfect forwarding for advanced C++ user. I am author of meta-template library and lambda library, who don't need verbose description of basics. Information in answer is very different from other question.


回答1:


Perfect forwarding is possible when the template parameter type contains a value category. (If this sentence doesn't make sense, take a minute to familiarize yourself with the problem at hand.)

Given:

template <typename T>
void foo(T&& x); 

Within the body of foo, T will either take the form of U or U&. The former means we were passed an rvalue, the latter means we were passed an lvalue. We can forward this fact on like so:

template <typename T>
void foo(T&& x)
{
    bar(std::forward<T>(x));
}

Pass an lvalue to foo, bar gets the same lvalue. Pass an rvalue to foo, bar gets the rvalue.

If you cannot distinguish a value category, then forwarding is of no use. It's only useful when you have a template parameter that's deduced in the same fashion as above. So yes, it has no use here:

template <typename T>
void foo(const T& x)
{
    // if this was called as foo(1), we're none the wiser
}



回答2:


I am answering to my own question as I didn't get satisfactory answer so far. If I will get even small improvement/addition to this - I will chose your answer as accepted.

In general std::forward will be beneficial with inner function if effect of perfect forwarding will be achieved. Otherwise it is superfluous.

Use std::forward to wrap inner function arg only if any of below is true:

  • inner function parameter is templated-rvalue-ref (now called "forwarding reference");
  • inner function has multiple overloads which differentiate based on parameter r/l-valueness;
  • inner function has multiple overloads which differentiate lvalue parameter based on constness;



回答3:


Use std::forward (on the formal parameter to a templated function, whose type is of the form T&&, T a type parameter of the template):

  • When the inner function call is the last use of the parameter in the outer function, and
  • When possible overloads of the inner function may or may not take the parameter as an rvalue reference.

The rationale is that, when an object is potentially passed as a parameter by rvalue reference (which is what you are allowing by using std::forward), it's information content may be destroyed. So, you only want to do it when you are sure you no longer have any use for that information content.

Example:

#include <utility>

template <class T> void f(T &&t);
template <class T> void g(const T &t);

template <class T>
void outer(bool f_first, T &&t)
  {
    if (f_first)
      {
        f(t);
        g(t);
      }
    else
      {
        g(t);
        f(std::forward<T>(t));
      }
  }

#include <string>

void foo(std::string s)
  {
    outer(true, s);
    outer(true, s + "x");
    outer(false, s);
    outer(false, std::move(s));
  }


来源:https://stackoverflow.com/questions/12048889/when-not-to-use-stdforward-with-r-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!