Ich versuche zu verstehen, was Metaprogrammierung allgemein und was es in C ++ im Besonderen ist
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:
Metaprogrammierung ist eine Programmiertechnik, bei der Computerprogramme andere Programme als ihre Daten behandeln können.
... kann verwendet werden, um Berechnungen von der Laufzeit zur Kompilierungszeit zu verschieben, um Code mithilfe von Berechnungen zur Kompilierungszeit zu generieren ...
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.
Meine Frage ist, ob alle Verwendungen von Vorlagen in C ++ als Metaprogrammierung kategorisiert sind
Nein ist es nicht.
Betrachten Sie als Referenz:
#define MAX(a,b) ((a) > (b) ? (a) : (b))
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:
template <typename T>
T max(T a, T b) { return a > b ? a : b; }
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 vonoperator<
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
template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };
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.