Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a difference between universal references and forwarding references?

An argument to this function will bind to an rvalue reference:

void f(int && i); 

However, an argument to this function will bind to either an rvalue or an lvalue reference:

template <typename T>   void f(T && t); 

I've often heard this referred to as a universal reference.
I've also heard it been called a forwarding reference.
Do they mean the same thing?
Is it only a forwarding reference if the function body calls std::forward?

like image 350
Trevor Hickey Avatar asked Sep 17 '16 22:09

Trevor Hickey


People also ask

What is C++ universal reference?

In a type declaration, “ && ” indicates either an rvalue reference or a universal reference – a reference that may resolve to either an lvalue reference or an rvalue reference. Universal references always have the form T&& for some deduced type T .

What is STD forward?

std::forward This is a helper function to allow perfect forwarding of arguments taken as rvalue references to deduced types, preserving any potential move semantics involved.

What is perfect forwarding C++?

What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.

What are rvalue references?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.


2 Answers

Do they mean the same thing?

Universal reference was a term Scott Meyers coined to describe the concept of taking an rvalue reference to a cv-unqualified template parameter, which can then be deduced as either a value or an lvalue reference.

At the time the C++ standard didn't have a special term for this, which was an oversight in C++11 and makes it hard to teach. This oversight was remedied by N4164, which added the following definition to [temp.deduct]:

A forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

Hence, the two mean the same thing, and the current C++ standard term is forwarding reference. The paper itself articulates why "forwarding reference" is a better term than "universal reference."

Is it only a forwarding reference if the function body calls std::forward?

Nope, what you do with a forwarding reference is irrelevant to the name. The concept forwarding reference simply refers to how the type T is deduced in:

template <class T> void foo(T&& ); // <==  

It does not need to be subsequently forwarded .

like image 122
Barry Avatar answered Sep 18 '22 20:09

Barry


Unfortunately, it's confusing, but they are nothing more than two names for the same thing.
Universal reference was proposed (I guess) by Meyers far ago (see here as an example).
Forwarding reference is picked up directly from the standardese. That's all.

like image 39
skypjack Avatar answered Sep 18 '22 20:09

skypjack