Is this a forwarding reference?

你说的曾经没有我的故事 提交于 2020-01-14 07:06:32

问题


The distinction between rvalue references and forwarding references was made clear enough in this example by Scott Meyers:

Widget&& var1 = someWidget;     // here, “&&” means rvalue reference (1)

auto&& var2 = var1;             // here, “&&” does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, “&&”does not mean rvalue reference (4)

Essentially the distinction happens when we have a deducible context, hence case (3) explicitly states that we have a vector<...>&& whereas the T in case (4) is to be deduced and (after applying reference collapsing rules) categorized in terms of "value category".

But what happens with a bit more complex pattern matching? Take the following case for example :

template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{

}

What does && mean here ?


回答1:


In your last example, arg is an rvalue reference.

A forwarding reference is an rvalue reference to a cv-unqualified template parameter

and Tuple<Ts...> is not a template parameter.

(Citation from [temp.deduct.call].)




回答2:


It is a rvalue reference, not a forwarding reference.

The easiest way to be sure is to try to pass an lvalue, if it fails, then it is a rvalue reference, if not, then a forwarding reference:

template<typename... Ts>
struct foo {};

//f function definition

int main() {
    foo<int, double> bar;
    f(bar); // fails! Cannot bind lvalue to rvalue reference
    f(foo<int, double>{}); // ok, rvalue is passed
}



回答3:


The concept forwarding reference is not a standard concept, it is usefull de recognize it when you see it, but if you want to understand and deal with it correctly you must understand reference arithmetics. (I believe Meyer's book has also a chapter about it)

What is behind the concept of a forwarding reference is the reference arithmetic:

  • && && = &&
  • && & = &
  • & && = &
  • & & = &

Let's simulate compiler template type deduction with a forwarding reference

template<class T>
void foo(T&&);
//...
const int i=42;
foo(i); // the compiler will defines T = const int &
         //          T&&  = const int & && = const int &
         // => the compiler instantiates void foo<const int &>(const int &);
foo(6*7);// the compiler will defines T = int
         //          T&&  = int &&
         // the compiler instantiates  void foo<int>(int &&);

in such a situation, the instantiation of the template foo can produces a function wich takes argument by lvalue reference or functions which takes arguments rvalue reference: a forwarding reference is either a rvalue reference or a lvalue reference, depending on template type deduction. It is named like this, because in such a situation, the parameter shall be passed either as an lvalue or as an xvalue, and this is the job of T&& std::forward<T>(T&& a)

If you declare a function has:

 template<class T>
 void foo(ATemplateClass<T> && a);

whatever the type deduced for T by the compiler, you'll get a rvalue reference paramater.



来源:https://stackoverflow.com/questions/40819058/is-this-a-forwarding-reference

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