Ich versuche zu verstehen, was Metaprogrammierung allgemein und was es in C ++ im Besonderen ist. Wenn ich nach C ++ - Metaprogrammierung suche, erhalte ich Tutorials zur Vorlagenmetaprogrammierung (TMP), aber keine Erklärung, ob nur eine bestimmte Verwendung von Vorlagen oder alle Verwendungen von Vorlagen kategorisiert werden.
Meine Frage ist, ob alle Verwendungen von Vorlagen in C ++ als Metaprogrammierung kategorisiert sind. Eine Erklärung, warum es ist oder nicht, wäre ebenfalls hilfreich. Vielen Dank.
Antworten:
Nein.
Nicht alle Verwendungen von Vorlagen in C ++ sind Metaprogrammierungen.
Natürlich handelt es sich um Definitionen, aber in C ++ ist "Metaprogrammierung" gleichbedeutend mit "Berechnung zur Kompilierungszeit".
Bei Vorlagen führen wir eine Metaprogrammierung durch (insbesondere eine Metaprogrammierung für Vorlagen), aber nicht alle Verwendungszwecke von Vorlagen sind Metaprogrammierungen.
Ein einfaches Gegenbeispiel
Das Vorstehende
printKeyVal()
ist eine Vorlagenfunktion , die in der Standardausgabe (also Laufzeit, nicht Kompilierungszeit) einige generische Werte druckt.Es kann nicht zur Kompilierungszeit ausgeführt werden, ist also "Vorlage", aber keine "Metaprogrammierung".
Allgemeiner:
std::vector
ist eine Vorlagenklasse , die die Speicherzuordnung verwendet. Und die Speicherzuordnung (bis C ++ 17; kann in Zukunft möglicherweise anders sein) kann nicht in Code zur Kompilierungszeit verwendet werden.So
std::vector
( im Gegensatz zu ,std::array
dass eine feste Größe, nicht die Speicherzuordnung verwendet) ist eine Template - Funktion , die nicht verwendet werden kann (wenn die Verwendung die Instantiierung eines beinhaltenstd::vector
für metaprogramming Objekt).quelle
printKeyVal
wird das während der Kompilierungszeit gemäß den Vorlagenargumenten definiertWas ist TMP in C ++?
Template Metaprogramming (TMP) in C ++ ist eine Technik zum Ausdrücken und Ausführen beliebiger Algorithmen in der Kompilierungszeit unter Verwendung von C ++ - Vorlagen. Dies wird normalerweise durch die Verwendung der Vorlagenspezialisierung zum Emulieren bedingter Verzweigungen und der rekursiven Vorlagendefinition zum Emulieren von Schleifen ermöglicht. Das bekannteste Beispiel ist eine faktorielle Berechnung zur Kompilierungszeit:
welches beide der oben genannten Techniken verwendet.
Ein weitaus häufiger jedoch ist eine Verwendung von TMP für Typ - Erkennung und Transformation statt tatsächlichen numerische Berechnung, beispielsweise eine Standard -
std::is_pointer
Programm ( Quelle ):Die meisten Dienstprogramme, die vom Standardheader type_traits bereitgestellt werden, werden mithilfe von TMP-Techniken implementiert.
Da die TMP - Algorithmen verwenden Typdefinitionen ausgedrückt, ist es erwähnenswert , dass TMP eine Form ist deklarative Programmierung , in der die Logik der Berechnung ohne die Verwendung von expliziten Kontrollfluss Aussagen ausgedrückt wird (
if
,else
,for
, etc ...).Ist jede Verwendung von C ++ - Vorlagen eine Metaprogrammierung?
Die kurze Antwort lautet: Nein. Wenn die Vorlagen nicht zum Ausdrücken eines Algorithmus zur Kompilierungszeit verwendet werden, handelt es sich nicht um eine Metaprogrammierung, sondern um eine generische Programmierung .
Das primäre Ziel für Vorlagen in C ++ Einführung war die generische Programmierung zu ermöglichen, die die gleichen Algorithmen zu ermöglichen , ist die Wiederverwendung (
find
,copy
,sort
, etc ...) und Datenstrukturen (vector
,list
,map
, etc ...) für alle Typen, einschließlich Benutzer- definierte, die bestimmte Anforderungen erfüllen.Tatsächlich wurde TMP in C ++ zufällig entdeckt und war nicht die beabsichtigte Verwendung von Vorlagen.
Zusammenfassend: Die Metaprogrammierung von Vorlagen in C ++ ist die Verwendung von Vorlagen zum Ausdrücken eines Algorithmus zur Kompilierungszeit. Die meisten (alle?) Anderen Verwendungen von C ++ - Vorlagen sind eine Form der generischen Programmierung.
quelle
Sie haben noch nicht gesagt, was Sie unter Metaprogrammierung im Allgemeinen verstehen , daher haben Ihre Antworten keinen gemeinsamen Ausgangspunkt.
Ich gehe davon aus, dass die Wikipedia-Definition dafür gut genug ist:
C ++ erlaubt im Allgemeinen keinen selbstmodifizierenden Code, daher ignoriere ich das. Ich entscheide mich auch dafür, den Präprozessor nicht zu zählen, da die Textsubstitution zur (oder wohl kurz vor) Kompilierungszeit nicht mit der Semantik des Programms identisch ist.
Nein ist es nicht.
Betrachten Sie als Referenz:
Das ist locker der Weg, um ein generisches (typunabhängiges) zu schreiben.
max
Funktion ohne Verwendung von Vorlagen . Ich habe bereits gesagt, dass ich den Präprozessor nicht als Metaprogrammierung zähle, aber auf jeden Fall erzeugt er immer identischen Code, wenn er verwendet wird.In einer späteren Übersetzungsphase wird einfach das Parsen dieses Codes delegiert und über den Typ und die
a>b
Definition für den Compiler nachgedacht . Hier wird zur Kompilierungszeit nichts ausgeführt , um je nach ... irgendetwas unterschiedlichen resultierenden Code zu erzeugen. Zur Kompilierungszeit wird nichts berechnet.Jetzt können wir die Vorlagenversion vergleichen:
Dies führt nicht einfach eine Textersetzung durch. Der Instanziierungsprozess ist komplexer, Namenssuchregeln und Überladungen können berücksichtigt werden, und in gewissem Sinne sind unterschiedliche Instanziierungen möglicherweise nicht textäquivalent (z. B. kann eine verwendet werden
bool ::operator< (T,T)
und einebool T::operator<(T const&)
oder was auch immer).Die Bedeutung jeder Instanziierung ist jedoch dieselbe (unter der Annahme kompatibler Definitionen von
operator<
für verschiedene Typen usw.), und zum Kompilierungszeitpunkt wurde nichts berechnet, außer dem üblichen (mechanischen) Prozess des Compilers zum Auflösen von Typen und Namen usw.Abgesehen davon reicht es definitiv nicht aus, dass Ihr Programm Anweisungen für den Compiler enthält, um ihm zu sagen, was zu tun ist , denn genau das ist die gesamte Programmierung.
Nun gibt es Randfälle wie
die tun eine Berechnung zur Kompilierung bewegen (und in diesem Fall ein nicht abbreche ein , da ich nicht das Terminal Fall gestört werden kann , schreiben), sind aber wohl nicht Metaprogrammierung.
Obwohl in der Wikipedia-Definition das Verschieben von Berechnungen zur Kompilierungszeit erwähnt wurde, handelt es sich nur um eine Wertberechnung - es wird keine Entscheidung zur Kompilierungszeit über die Struktur oder Semantik Ihres Codes getroffen.
quelle
Wenn Sie C ++ - Funktionen mit Vorlagen schreiben, schreiben Sie "Anweisungen" für den Compiler, um ihm mitzuteilen, was zu tun ist, wenn Aufrufe der Funktion auftreten. In diesem Sinne schreiben Sie keinen Code direkt, daher nennen wir ihn Metaprogrammierung.
Ja, jeder C ++ - Code mit Vorlagen wird als Metaprogrammierung betrachtet
Beachten Sie, dass nur die Teile, die Vorlagenfunktionen oder -klassen definieren, Metaprogrammierung sind. Reguläre Funktionen und Klassen werden als reguläres C ++ kategorisiert!
quelle
std::vector
einen Compiler an, ein Programm zu erstellen (es ist also tatsächlich Meta), aber die Anweisung selbst ist kaum ein Programm. Die meisten Leute denken nicht daran, Makros "Metaprogrammierung" zu verwenden.