Werden alle Vorlagen in der C ++ - Metaprogrammierung verwendet?

8

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.

joaerl
quelle
1
Vergleichen Sie mit CL-Makros und sehen Sie sich die zehnte Regel von Greenspun an. en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
stark
1
TMP ist nicht die einzige Möglichkeit zur Metaprogrammierung. Man kann Metaprogrammierung auch mit Makros (uhh) und constexpr- Funktionen durchführen. Constexpr kann einfacher zu implementieren sein als TMP.
zett42
1
@ zett42 Ich bin mir nicht sicher, ob das bloße Ausführen von Code zur Kompilierungszeit als "Metaprogrammierung" angesehen werden sollte. Denn das ist nicht Programmieren , sondern Rechnen. Es wird lediglich die Ausführung von der Laufzeit zur Kompilierungszeit verschoben. Die Metaprogrammierung in C ++ unterscheidet sich davon, da sie Code (Vorlagen, Makros) generiert.
Johannes Schaub - 5.

Antworten:

2

Meine Frage ist, ob alle Verwendungen von Vorlagen in C ++ als Metaprogrammierung kategorisiert sind.

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

template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
 { std::cout << k << ": " << v << std::endl; }

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::vectorist 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::arraydass eine feste Größe, nicht die Speicherzuordnung verwendet) ist eine Template - Funktion , die nicht verwendet werden kann (wenn die Verwendung die Instantiierung eines beinhalten std::vectorfür metaprogramming Objekt).

max66
quelle
Für jede Funktion, die von der Vorlage abhängt, ist jedoch mindestens eine Metaprogrammierung erforderlich. In Ihrem Beispiel printKeyValwird das während der Kompilierungszeit gemäß den Vorlagenargumenten definiert
SomeWittyUsername
Wenn Sie programmieren, schreiben Sie Code. Sie "berechnen" keine Dinge. Also würde ich "Metaprogrammierung" als "Code schreiben, um Code zu schreiben" definieren. Und genau darum geht es in jeder Vorlage. Ich bin mir bewusst, dass die Metaprogrammierung von Vorlagen häufig für die Berechnung der "Kompilierungszeit" verwendet wird, aber ich persönlich würde dafür einen anderen Begriff verwenden (ich bin sicher, dass ich dies in der Vergangenheit nicht getan habe, also entschuldige mich).
Johannes Schaub - Litb
@ JohannesSchaub-litb - Es geht um Sprache und Definitionen (und ich habe das zusätzliche Handicap, dass ich die englische Sprache nicht gut kenne) und ich bin damit einverstanden, dass eine Definition von "Metaprogrammierung", die alle Vorlagen enthält, möglich ist und vielleicht auch angemessen. Was ich sage ist, dass in der C ++ - Community der Begriff "Metaprogrammierung" mit einer anderen Bedeutung verwendet wird, die sich überschneidet, aber nicht alle Vorlagenverwendungen umfasst. Vielleicht irre ich mich ... könnte eine interessante Umfrage sein.
max66
Vielleicht heißt es "Metaprogrammierung" nur, wenn der Code der Vorlage nicht mehr 1: 1 für jeden Typ dupliziert wird, denn wenn er 1: 1 dupliziert wird, ist der Vorlagencode rein passiv und die gesamte "Metaprogrammierung" wird vom Compiler durchgeführt . Wenn es eine Spezialisierung oder ein statisches If- oder Overload-Dispatching oder ähnliches gibt, entscheidet der Code selbst, was generiert wird. Dies scheint Ds Haltung zu sein: tour.dlang.org/tour/en/gems/template-meta-programming
Johannes Schaub - litb
@SomeWittyUsername - Es scheint mir, dass Sie eine Definition von "Metaprogrammierung" verwenden, die sich, absolut legitim und vielleicht auch vernünftig, von der unterscheidet, die die C ++ - Community de facto verwendet: grob gesagt: "Metaprogrammierung == Kompilierzeitausführung ". Vielleicht irre ich mich und die Community verwendet hauptsächlich eine Definition, die alle Vorlagenverwendungen enthält ... könnte eine interessante Umfrage sein, nehme ich an.
max66
1

Was 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:

template <unsigned int n>
struct factorial {
    // recursive definition to emulate a loop or a regular recursion
    enum { value = n * factorial<n - 1>::value };
};

// specialization that describes "break" condition for the recursion
template <>
struct factorial<0> { 
    enum { value = 1 };
};

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_pointerProgramm ( Quelle ):

// generic definition that emulates "false" conditional branch
template<class T>
struct is_pointer_helper : std::false_type {};

// a specialization that emulates "true" conditional branch
template<class T>
struct is_pointer_helper<T*> : std::true_type {};

template<class T>
struct is_pointer : is_pointer_helper< typename std::remove_cv<T>::type > {};

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.

r3mus n0x
quelle
0

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>bDefinition 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.

Nutzlos
quelle
-1

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!

Xatyrian
quelle
1
Wenn ich "cp a.txt b.txt" in Bash eingebe, programmiert dies nicht, obwohl ich eine vollständige Programmierumgebung verwende. Ebenso weise ich std::vectoreinen 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.
n. 'Pronomen' m.
1
Ihre Antwort ist einfach falsch! Bitte lesen Sie die anderen Antworten in diesem Thread, um ein grundlegendes Verständnis dafür zu erhalten, was MTP bedeutet!
Klaus
1
Wenn Sie C ++ ohne Vorlagen schreiben, schreiben Sie Anweisungen für den Compiler. Die Tatsache, dass Vorlagen dem Compiler mitteilen, was zu tun ist, kann nicht ausreichen, um die Programmierung von der Metaprogrammierung zu unterscheiden
nutzlos
1
@ JohannesSchaub-litb Im Kontext von C ++ hat der Begriff "Metaprogrammierung" eine spezifische Bedeutung, die sich von seiner allgemeinen Bedeutung unterscheidet . IIRC bezog sich zunächst auf die entdeckte A. ++ - Funktion, die A.Alexandrescu in seinem Buch Modern C ++ Design geprägt hatte . Die klassische Verwendung von Vorlagen in C ++ ist keine Metaprogrammierung (es sei denn, Sie verwenden den Nicht-C ++ - Begriff Metaprogrammierung).
YSC
1
Vom OP Frage: „Ich versuche , was metaprogramming ist allgemein und was zu verstehen , ist es in C ++ insbesondere“ . Ich denke, Ihr Blickwinkel ist in Ordnung und würde eine hervorragende Antwort darstellen. Aber das ist es nicht. -1
YSC