2016-08-07 84 views
15

Ich habe gelesen über die universellen Referenzen in Scotts letzten Meisterstück über die C++ 11 und 14 mit dem gesagt trotz eines Arguments entweder Lvalue oder einem Rvalue-Typ zugewiesen Referenzparameter Es gibt etwas dazwischen, das als universelle Referenz bezeichnet wird, die basierend auf dem Typmerkmal eines übergebenen Arguments entweder zu l/rvalue abgeleitet werden konnte. Ich konnte verstehen, was die Parameter als universelle Referenz macht aber die eine Sache, die mich nicht klar, warum tut, ist das Hinzufügen const den Typ Parameter const T&& p die p als rvalue machen:Warum fügt "const" die universelle Referenz als rvalue hinzu

template<typename T> 
void f(T&& param); // param is an universal reference 

template<typename T> 
void f(const T&& param); // param is an rvalue reference 

Hat die const mehr tun, als dies wenn es dem Referenzparameter zugewiesen ist.

Antwort

11

Der offizielle Name ist keine universelle Referenz, sondern forwarding reference. Die Standard Staaten, die nur rvalue Verweise auf cv-unqualifizierte Template-Parameter in diese Kategorie fallen:

14.8.2.1 Ableiten Vorlage Argumente aus einem Funktionsaufruf [temp.deduct.call]

3 Wenn P ein cv-qualifizierter Typ ist, werden die Cv-Qualifikationsmerkmale der obersten Ebene des P-Typs für die Typableitung ignoriert. Wenn P ein Referenztyp ist, wird der Typ , auf den sich P bezieht, für den Typabzug verwendet. Eine Weiterleitungsreferenz ist ein R-Wert-Verweis auf einen cv-unqualifizierten Vorlagenparameter. Wenn P eine Forwarding-Referenz ist und das Argument ein Lvalue ist, wird der Typ "Lvalue Referenz auf A" anstelle von A für Typ Abzug verwendet. [Beispiel:

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

- Ende Beispiel]

const T&& Zulassen als Forwarding Referenzen zu verhalten, wäre es unmöglich machen, eine Template-Funktion zu überlasten, die nur eine R-Wert Referenz als Parameter übernehmen.

aktualisieren: als @HowardHinnant in den Kommentaren erwähnt, tut const T&& seinen Nutzen haben (siehe this Q&A auch).

+1

Um an den Teil von Item 24 in _Effective Modern C++ _, das das OP verwirrte, zurückzubinden, beschreiben Scott (lose) universelle Referenzen als rvalue-Referenzen _in einem Typ, der Kontext kontextupliziert. Der erste (nicht hervorgehobene) Satz in der obigen 14.8.2.1-Standardzitat (_ "Wenn P ein cv-qualifizierter Typ ist, werden die cv-Qualifikationsmerkmale der oberen Ebene des P-Typs ** für die Typableitung **" _) eindeutig ignoriert erklärt Scotts Aussage, dass _ "selbst die einfache Anwesenheit eines" const "Qualifikators ausreicht, um eine Referenz vom universellen zu disqualifizieren" (Zitat aus Buch, Punkt 24). – dfri

+1

@dfri Danke, ich hatte keine digitale Kopie von EMC++ in der Nähe. – TemplateRex

+2

Mehr Motivation in Bezug auf das Warum: Manchmal müssen wir sagen: Binden Sie nicht an einen R-Wert, sondern nur an L-Werte: 'template void cref (const T &&) = löschen;'. –