2. Basierend auf Meyers „Effective and Modern C ++“ - Details zur Inferenz des Vorlagentyps für Arrays

Guten Tag, lieber Leser!


Dieser Artikel ist der zweite in einer Reihe von abstrakten Artikeln, die ich schreiben werde, während ich Scott Meyers Bestseller Effective and Modern c ++ lese. Jeder dieser Artikel verfügt über ein separates Verzeichnis in einem speziell auf github.com eingerichteten Projekt mit Live-Beispielen für die Verwendung dessen, was wir heute lesen.


Dieser Artikel ergänzt die Regeln für die Typinferenz aus dem vorherigen Artikel und erläutert bestimmte Aspekte der Inferenz für Vorlagentypen für Argumente, die ein Array und eine Funktion sind.


Mustertypinferenz für Array


Der c ++ - Compiler hat eine solche Eigenschaft, dass ein deklariertes Array immer, wenn es an eine Vorlagenfunktion mit einem Parameter übergeben wird, der nicht als Link deklariert ist, immer in einen Zeiger auf den gespeicherten Typ konvertiert wird. Wenn der Parameter als Link deklariert wird, wird eine solche Konvertierung nicht durchgeführt.


Vorlagenfunktionen:


Zunächst werde ich den Code der Vorlagenfunktionen angeben, die die begehrten Typen ableiten, und dann den Ableitungsprozess selbst:


template<typename T> void paramDeductInfo(T param, const char *initType) { std::cout << initType << " -> (T param) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; }; template<typename T> void refParamDeductInfo(T &param, const char *initType) { std::cout << initType << " -> (T &param) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; }; 

Typinferenz:


 cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CHAR"); char charSeq[] = "Hi everyone!"; paramDeductInfo(charSeq, "char []"); refParamDeductInfo(charSeq, "char []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF INT"); int intSeq[] = {1, 2, 3}; paramDeductInfo(intSeq, "int []"); refParamDeductInfo(intSeq, "int []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CLASS A"); class A { } const classASeq[] = {A(), A(), A()}; paramDeductInfo(classASeq, "class A[]"); refParamDeductInfo(classASeq, "class A[]"); 

Der folgende Pseudocode spiegelt die Ausgabe dieser Anweisungen an die Konsole wider:


 ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CHAR ************************************************************************************************************************ char [] -> (T param) -> char* char [] -> (T &param) -> char [13] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF INT ************************************************************************************************************************ int [] -> (T param) -> int* int [] -> (T &param) -> int [3] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CLASS A ************************************************************************************************************************ class A[] -> (T param) -> main::A const* class A[] -> (T &param) -> main::A const [3] 

Beispiel 1 - Analyse der Länge eines Arrays zur Kompilierungszeit


Darüber hinaus speichert der Ausgabetyp des Arrays Informationen über seine Größe, die in einer Vorlagenfunktion verwendet werden können, um die Größe des Arrays während der Kompilierung zu ändern oder effizienteren Code zu generieren.


Ich habe diese Funktion in der Funktion printCaption verwendet, um die Länge des Headers zu begrenzen, der zur Kompilierungszeit in der Befehlszeile angezeigt wird. Eine Kleinigkeit, aber nett.


 namespace cli { template<typename T, std::size_t N> constexpr void printCaption(T (&capValue)[N]) { static_assert(N <= 121, "caption length should be less than 120"); std::cout << std::endl << "*******************************************************************************" << std::endl << capValue << std::endl << "*******************************************************************************" << std::endl << std::endl; }; } 

Lassen Sie uns prüfen, ob ein Fehler auftritt, wenn wir einen offensichtlich unangemessenen Header einführen.


 cli::printCaption("123456789 123456789 123456789 123456789 123456789 123456789 123456789" "123456789 123456789 123456789 123456789 123456789 !"); 

Und hier sind Sie bitte, na ja, ist es nicht wunderbar?


 /...sources/cli.h:12:3: error: static assertion failed: caption length should be less than 120 static_assert(N <= 121, "caption length should be less than 120"); ^~~~~~~~~~~~~ 

Beispiel 2 - foreach auf einem Array im Speicher


Ich denke, hier ist ein anderer solcher Ansatz, der nützlich erscheinen kann, wenn wir in der Kompilierungszeit eine Arraygröße haben. Warum nicht eine Schleife in einem solchen Array organisieren?


 template<typename T, size_t N, typename F> void forEachOnAnArray(T (&inmemArray)[N], F &callback) { for (int i = 0; i < N; ++i) callback(inmemArray[i]); }; 

Diese Funktion wird wie folgt verwendet:


  auto printInt = [](int value) { std::cout << " " << value; }; forEachOnAnArray(intSeq, printInt); 

Im Allgemeinen ist die Verwendung dieser Funktion keineswegs darauf beschränkt, die Größe des Arrays herauszuziehen.


Typinferenz für eine Funktion


Die Typinferenz für die Meyers-Funktion ist kurz. Er erwähnt genau, dass sie auf die gleiche Weise wie bei Arrays auf einen Zeiger reduziert werden, außer wenn der Parameter der Vorlagenfunktion, mit der unser Funktionstyp angezeigt werden soll, nicht als Link deklariert ist.


Er hätte wahrscheinlich über eine Art Template-Wrapper für Funktionen sprechen sollen, aber ich denke, das geht einfach über die Frage nach effizientem und modernem C ++ hinaus.


Wir, mein lieber Leser, werden auf jeden Fall auf dieses Thema zurückkommen!


Danke und einen schönen Tag !!

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


All Articles