Core knowledge of C + + 11-17 template (x) — distinguishing universal references and right value references

Time:2021-9-18
  • Introduction
  • How to distinguish

Introduction

T&&Right value references are not always used in Code:

void f(Widget&& param);      // rvalue reference

Widget&& var1 = Widget();      // rvalue reference

auto&& var2 = var1;        // not rvalue reference


template
void f(std::vector&& param);      // rvalue reference


template
void f(T&& param);     // not rvalue reference

T&&Represents two meanings:

  • rvalue reference
  • Universal references, or forwarding references

How to distinguish

Universal references generally appear in two scenarios:

  • Template parameters
template
void f(T&& param); // param is a universal reference
  • Auto declaration
auto&& var2 = var1; // var2 is a universal reference

Let’s discuss these two scenarios separately.

Template parameters

We note that where universal reference is involved, there will be a parameter derivation process, such as T and var2 above. However, the right value reference does not have this process:

void f(Widget&& param);        // no type deduction; param is an rvalue reference

Widget&& var1 = Widget();     // no type deduction; var1 is an rvalue reference

However, even if the statement is designed to parameter derivation, it is not necessarily a universal reference. For example:

template
void f(std::vector&& param);       // param is an rvalue reference


std::vector v;
f(v); // error! can't bind lvalue to rvalue reference

This is easy to understand. Universal references need to rely on expressions to initialize whether they are R-value references or l-value references, but the above example does not show this. It only infers the type of T, but the type of param is always the samestd::vector&&

Let’s give another example in vector:

template> 
class vector { 
public:

void push_back(T&& x);      // rvalue reference


template  
void emplace_back(Args&&... args);      // universal reference
};
  • push_back(T&& x)T & & in is an R-value reference, because although it is T & &, it does not involve parameter derivation. When push_ When the back is instantiated, the actual call is similar to:
std::vector v;

...
class vector> {
public:
void push_back(Widget&& x);       // rvalue reference
…
};

It is obvious that there is no parameter derivation process at this time.

  • template emplace_back(Args&&... args)MediumArgs&&Is a universal reference. Args and T are independent of each other, so args has an independent parameter inference process.

const disqualify universal reference

Interestingly, when const is added to the parameter, it must be an R-value reference:

template  int f(T&& heisenreference);
template  int g(const T&&);

int i;
int n1 = f(i);         // calls f(int&)
int n2 = f(0);     // calls f(int&&)
int n3 = g(i); // error: would call g(const int&&), which would bind an rvalue reference to an lvalue

As for why there is this provision, follow why addingconstThere are two reasons for making the universal reference as rvalue:

  • const T&&Allows you to overload a function template that accepts only R-value references. Ifconst T&&If it is also regarded as a universal reference, there will be no way for the function to accept only R-value references.
  • Show disable a function from accepting R-value References:template void cref(const T&&) = delete;

Auto declaration

For auto scenes, allauto&&All are universal references, because it always has the process of parameter derivation. For example, define a lambda that records the execution time of a function (auto is allowed to declare lambda functions in C + + 14):

auto timeFuncInvocation = [](auto &&func, auto &&... params) {  
  start timer;
  std::forward(func)(                      // invoke func
      std::forward(params)...      // on params
  );
  stop timer and record elapsed time;
};

(end)

Friends can take note of my official account and get the most timely updates.

Recommended Today

Seven Python code review tools recommended

althoughPythonLanguage is one of the most flexible development languages at present, but developers often abuse its flexibility and even violate relevant standards. So PythoncodeThe following common quality problems often occur: Some unused modules have been imported Function is missing arguments in various calls The appropriate format indentation is missing Missing appropriate spaces before and after […]