1. Basierend auf Meyers "Effektives und modernes c ++" - Inferenz des Vorlagentyps

Guten Tag, lieber Leser!


Dieser Artikel ist der erste in einer Reihe von abstrakten Artikeln, die ich schreiben werde, wĂ€hrend ich Scott Meyers 'Buch Effective and Modern c ++ lese. Jeder dieser Artikel verfĂŒgt ĂŒber ein separates Verzeichnis in einem speziell auf github.com eingerichteten Projekt mit Beispielen fĂŒr die Verwendung der beschriebenen Funktionen und Techniken.


Inferenz des Vorlagentyps


Erfolgreiches Design ist, wenn der Verbraucher nicht weiß, wie das GerĂ€t funktioniert, aber alles zu ihm passt.


Die Schlussfolgerung des Vorlagentyps ist beispielsweise, wenn eine Vorlagenfunktion vorhanden ist und diese ohne Vorlagen- und spitze Klammern aufgerufen wird. Gleichzeitig errÀt der Compiler, welchen Typ er in einem bestimmten Objekt der Funktion verwenden muss.


Meyers teilt den Typ - "T" , der angezeigt wird, und den Typ - "ParamType" , der vom Programmierer in der Definition des Parameters vorgeschrieben wird.


1. Parameteransicht - Link oder Zeiger


Um die Ableitungsregel schnell zu verstehen, werde ich sie in Form einer Vorlage wiedergeben:


Eingabetyp -> Typ, Parameter -> Ausgabetyp [, endgĂŒltiger Parametertyp ]


Beispiel mit einem Link:


template<typename T> //   T void func(T& param) //   - T& int x = 0; //   int func(x); 

Wenn der Typ T abgeleitet wird, wird die ReferenzialitĂ€t (*, &) verworfen, da sie bereits bei der Definition der Funktion angegeben wird, als ob dies bedeutet, dass Sie dort etwas ĂŒbergeben. Wir gehen davon aus, dass dies kein Link ist, da die ReferenzialitĂ€t bereits am Ort des Verbrauchs hinzugefĂŒgt wurde. in unserer Funktion f "


Nach dem gleichen Prinzip wird die Konstanz verworfen, wenn sie im Funktionsparameter angegeben ist. Links, Zeigern und Konstanz wird sozusagen eine exklusive Maske auferlegt.


Auszahlungsschema


 //   int —> (T & param) —> int; const int —> (T & param) —> const int; const int & —> (T & param) —> const int //   int —> (const T & param) —> int; const int —> (const T & param) —> int; const int & —> (const T & param) —> int; //   int * —> (T * param) —> int; const int —> (T * param) —> const int; const int * —> (T * param) —> const int; //   int * —> (const T * param) —> int; const int —> (const T * param) —> int; const int * —> (const T * param) —> int; 

2. Art des Arguments - universelle Referenz


Scott erwĂ€hnt, dass universelle VerknĂŒpfungen spĂ€ter in Betracht gezogen werden, daher mĂŒssen die Regeln fĂŒr die Parameter, die er hier in rvalue und lvalue unterteilt, nur mit wenig Nachdenken in Erinnerung bleiben.


 template<typename T> void func(const T&& param) 

Inferenzregeln fĂŒr lWert


Dies ist laut Scott der einzige Fall, in dem T als Referenz ausgegeben wird.
In den folgenden Beispielen ist der Typ des Parameters in der Funktionsbeschreibung eine universelle Wertreferenz . Es ist ersichtlich, dass T je nach Link oder als konstanter Link angezeigt wird
Aus dem Eingabeargument ergibt sich in diesem Fall auch der Typ des Parameter param selbst.


 lvalue int —> (T &&param) —> int &, param - int& lvalue const int —> (T &&param) —> const int &, param - const int& lvalue const int & —> (T &&param) —> const int &, param - const int& 

Der Typ des Parameters selbst wird ebenfalls ersetzt. Ich denke, dies liegt an der Tatsache, dass die Sprache eine Wertvariable nicht berĂŒcksichtigen kann, die irgendwo ĂŒber der zugewiesenen liegt, die weiter verschoben werden kann. Wir werden es spĂ€ter herausfinden, wenn wir zu universellen Links kommen.
Um zu ĂŒberprĂŒfen, ob T wirklich eine Typreferenz ist , habe ich T myVar in den Hauptteil der Vorlagenfunktion geschrieben, die dieses T sowohl anzeigte als auch erwartungsgemĂ€ĂŸ eine Nachricht erhielt - "als Referenz deklariert, aber nicht initialisiert" - den Link :)


Inferenzregeln fĂŒr rWert


Es gelten die „normalen“ Regeln von Absatz 1.


 rvalue int —> (T &&param) —> int, param - int&& 

Es ist bereits offensichtlich, dass universelle Referenzen nur fĂŒr rvalue-temporĂ€re Objekte "enthalten" sind, in anderen FĂ€llen, wenn das Argument keine universelle Referenz ist, wird rvalue, lvalue nicht unterschieden


3. Wert ĂŒbergeben (wie er ist)


Bei der Übergabe von Werten wird die Konstanz und ReferenzialitĂ€t des ursprĂŒnglichen Arguments als unnötig verworfen, da es sich um völlig neue unabhĂ€ngige Objekte handelt. Warum benötigen sie Qualifizierer fĂŒr das, womit sie nicht verbunden sind?


 int —> (T param) —> int const int —> (T param) —> int const int & —> (T param) —> int //       ,     const char * const —> (T param) —> const char * 

Ich nehme an, dass andere verrĂŒckte und unlogische Kombinationen fast immer Kompilierungsfehler verursachen. Es stellt sich heraus, dass die Arbeit des Compilers verstĂ€ndlich ist. Sie mĂŒssen diese ErklĂ€rungen nur einmal anhören.

Source: https://habr.com/ru/post/de414233/


All Articles