Sind C ++ - Vorlagen nur eine Art verherrlichte Makros?

27

Aus verschiedenen Vergleichen zwischen C ++ - Vorlagen und C # / Java-Generika wie diesem

https://stackoverflow.com/questions/31693/was-sind-die-unterschiede- zwischen-generika-in-c-und-java-und-vorlagen-in-c/31929#31929

Ich habe die Vorstellung, dass C ++ - Vorlagen durch eine Art Vorverarbeitung (Ersetzen von einfachem Text vor dem Parsen) implementiert und nicht kompiliert werden. Da die Typüberprüfung in C ++ - Vorlagen C-Makros ähnelt. Ich meine, wenn es einige Fehler gibt, handelt es sich um Fehler aus dem generierten Code nach der Verarbeitung von Codeblöcken mit Vorlagen, nicht aus den Vorlagen selbst. Mit anderen Worten, sie sind nur eine Art obere Version von Makros in C.

Dann fand ich einige andere Fakten, die dies unterstützen.

  • Ich dachte, wenn C ++ - Vorlagen durch Vorverarbeitung implementiert werden, wird es Probleme mit der dynamischen Verknüpfung (mit DLL) geben. Und ein schnelles googeln unterstützte dies.

  • Ein weiterer Punkt ist, dass Integer-Konstanten als Argumente an die Vorlagen übergeben werden können. Und es unterstützt sogar eine Art Rekursion. Diese Rekursion ist jedoch nicht im kompilierten Assembly- / Maschinencode enthalten. Die Rekursionssache wird in der Kompilierungszeit verwaltet, indem für jeden rekursiven Aufruf eine Funktion generiert wird und somit eine größere, aber schneller ausführbare Binärdatei vorliegt.

Im Gegensatz zu C-Makros verfügt es über einige überlegene Fähigkeiten. Aber ist C ++ Template nicht mit einer Art Vorverarbeitung implementiert? Wie ist dies in verschiedenen C ++ - Compilern implementiert?

Gulshan
quelle
19
Nee. C ++ Vorlagen werden kompiliert.
Edward Strange
2
Was ist Ihre Definition von "Vorverarbeitung"? Und von "kompilieren"? Eine ausreichend breite Definition von "Vorverarbeitung" könnte alles umfassen, was ein Compiler tut. Schließlich verarbeitet ein Compiler die Quelle wirklich nur, bevor sie ausgeführt wird, nicht wahr?
James McNellis
@ James McNellis IMHO, wenn Sie nur die Vorverarbeitung von allen anderen für die Kompilierung durchgeführten Dingen unterscheiden können, reicht es aus, meine Frage zu verstehen. Zur Klärung der Präprozessor- en.wikipedia.org/wiki/Preprocessor#Lexical_preprocessors
Gulshan
6
Wenn Sie sich auf diese Form der Vorverarbeitung beziehen, dann sind C ++ - Vorlagen absolut keine verherrlichten Makros.
James McNellis
1
Die Vorlagensprache ist tatsächlich vollständig, sodass sie weit mehr als nur erweiterte Makros sind.
Davidk01

Antworten:

9

C ++ - Vorlagen sind eine Art von Lisp-Makros (oder sogar Scheme-Makros). Es ist eine Turing-vollständige Sprache, die in der Kompilierungszeit ausgewertet wird, jedoch stark eingeschränkt ist, da von dieser Sprache kein Zugriff auf die zugrunde liegende C ++ - Umgebung besteht. Ja, C ++ - Vorlagen können als eine Form der Vorverarbeitung angesehen werden, mit einer sehr begrenzten Interaktion mit dem generierten Code.

SK-Logik
quelle
2
"aber es ist stark eingeschränkt, da es keinen Zugriff von dieser Sprache auf die zugrunde liegende C ++ - Umgebung gibt." -- Was heißt das? Ich habe versucht, diese Aussage zu analysieren, bin aber gescheitert.
quant_dev
2
Ähm, eigentlich ... github.com/kmichel/bf0x
Anton Golov
3
@ SK-Logik: Als Nebenwirkung , C ++ 11 ist C ++, es sei denn , Sie (pedantisch) behandeln verschiedene Versionen derselben Sprache wie verschiedene Sprachen.
Jon Purdy
3
@ Jon Purdy, C ++ 11 existierte (offiziell) zum Zeitpunkt dieser Antwort nicht. Heutzutage wäre ein Beispiel komplizierter gewesen, wie das Zerlegen einer Datenstruktur, die Verwendung einer Bibliotheksfunktion usw.
SK-logic
1
@ SK-logic: Kennen Sie die Implementierung von C ++ mit Lisp-ähnlichen Makros? Ich habe die Einschränkungen von Vorlagen satt. Ein Beispiel für eine Syntaxsprache im C ++ - Stil mit einem leistungsstarken Makrosystem in Haxe: haxe.org/manual/macros . (Hilft mir nicht, weil ich C ++ für seinen Zweck verwende - Programmierung von 8-Bit-Mikrocontrollern; für alles andere gibt es bessere Sprachen).
Pfalcon
41

Der wahrscheinlich größte Unterschied besteht darin, dass C-Makros in der Vorverarbeitungsphase erweitert werden, bevor eine andere Kompilierung durchgeführt wird, während C ++ - Vorlagen Teil der Kompilierung sind. Dies bedeutet, dass C ++ - Vorlagen unter anderem typensensitiv und bereichsspezifisch sind und keine einfache Textsubstitution darstellen. Sie können zu echten Funktionen kompiliert werden und vermeiden daher die meisten Probleme, die Makros haben. Wenn Sie typbewusst arbeiten, können Sie allgemeine oder spezielle swapFunktionen verwenden. Beispielsweise können Sie problemlos eine Vorlagenfunktion bereitstellen und Spezialisierungen schreiben, die auch dann gut funktionieren, wenn die Objekte den Heapspeicher verwalten.

Daher gilt: C ++ - Vorlagen werden nicht im selben Sinne wie Makros vorverarbeitet, sie sind keine Art von C-Makro, und es ist unmöglich, C-Makros zum Duplizieren der Aufgaben von Vorlagen zu verwenden.

Vorlagen befinden sich in Header-Dateien, nicht in verknüpften Bibliotheken, true, aber wenn Sie eine DLL-Datei bereitstellen, stellen Sie vermutlich auch eine Header-Datei zur Verfügung.

David Thornley
quelle
12
Sie müssen nicht in der Header-Datei leben (dies ist nur die einfachste Methode, um sie zu verwenden). Sie können sie in einer Quelldatei definieren und die Instanziierung der Vorlage in der Quelldatei (Zusammenstellungseinheit) manuell erzwingen. Durch das Verknüpfen werden die Instantiierungen wie gewohnt übernommen (dies ist eine Technik, mit der Vorlagen auf bestimmte Typen beschränkt werden und nicht alle generischen Typen zugelassen werden).
Martin York
@Martin: Ich bin mir nicht sicher, ob diese Technik (solange sie unterstützt wird) tatsächlich explizit vom Standard unterstützt wird. Andernfalls hätten alle Compiler bereits exportimplementiert. Ich weiß, dass es für Funktionen funktioniert, aber ich bezweifle, dass es für Klassen funktioniert: Wie würden Sie ihre Größe kennen?
Matthieu M.
@ Matthieu M: Das hat nichts mit dem Export-Schlüsselwort zu tun. Es befasst sich mit der "expliziten" Template-Instanziierung und ist im Standard gut definiert.
Martin York
2
@Matthieu M .: Wenn der Compiler die Signatur einer Funktion kennt und der Linker eine Implementierung finden kann, ist alles cool. Dies gilt unabhängig davon, ob es sich bei der Funktion um eine Vorlagenfunktion handelt. In der Praxis leben sie in der Regel in Header-Dateien, da das Erzwingen bestimmter Instantiierungen in der Regel mehr Arbeit kostet als es sich lohnt, aber Martin hat Recht, wenn er die Alternative nennt.
David Thornley
Ich weiß, dass es für spezielle Funktionen funktioniert. Ich bin mir aber auch ziemlich sicher, dass es für Klassen nicht funktioniert, was mein Punkt war. Ich denke, es funktioniert auch für Methoden aus spezialisierten Klassen, aber ich weiß nicht, ob dies Standard ist oder nicht.
Matthieu M.
5

Ist es wichtig, wie sie implementiert werden? Die frühen C ++ - Compiler waren nur Pre-Prozessoren, die den Code an den AC-Compiler weitergaben. Dies bedeutet nicht, dass C ++ nur ein verherrlichtes Makro ist.

Vorlagen machen Makros überflüssig, da sie eine sicherere, effizientere und spezifischere Methode zur Implementierung von Code für mehrere Typen bieten (auch wenn ich das nicht für richtig halte).

Es gibt eine Vielzahl von Möglichkeiten, Templatetypcode in c zu erstellen, von denen keine sehr hilfreich ist, wenn Sie über einfache Typen hinausgehen.

Martin Beckett
quelle
Ich habe nicht gesagt, dass C ++ ein verherrlichtes Makro ist. Ich bewundere C ++ sehr. Einfach nur neugierig sein.
Gulshan
2
@ Gulshan: Nein, dazu hast du nichts gesagt. Trotzdem funktionierten die frühen C ++ - Compiler so (mit der Ausnahme, dass CFront eher ein Compiler als nur ein Makro-Präprozessor war), und Ihre Aussagen zu C ++ - Vorlagen gelten in etwa für die frühen C ++ - Versionen.
David Thornley
CFront kompilierte C ++ bis C. Die Grenze zwischen Präprozessor und Compiler ist klar definiert: Ein Compiler versucht, seine Eingabe über Parsing, AST- Erstellung usw. zu verstehen, während ein Präprozessor dies nicht tut, z. B. indem er nur Text- oder Tokensubstitution verwendet.
Jon Purdy
1
Ich denke, was David damit gemeint hat, ist, dass es eine zugrunde liegende Teilmenge von C ++ gibt und dass Templates als eine Art von Makros gedacht werden können, die verwendet werden, um ein Programm in dieser Teilmenge zu generieren, das dann als eine weitere separate Stufe kompiliert werden kann.
Giorgio
5

Es gibt einige Unterschiede; Vorlagen können beispielsweise verwendet werden, um bei Bedarf eine Funktionsüberladung zu instanziieren, während Sie bei Makros das Makro einmal für jede mögliche Überladung erweitern müssen, um es für den Compiler sichtbar zu machen von nicht verwendetem Code.

Ein weiterer Unterschied besteht darin, dass Vorlagen Namespaces berücksichtigen.

Simon Richter
quelle
2

IMHO, C ++ - Vorlagen und C-Makros sollten zwei völlig unterschiedliche Probleme lösen. Die ursprüngliche C ++ - Standardvorlagenbibliothek war ein Mechanismus, um Containerklassen (Arrays, verknüpfte Listen usw.) sauber von den allgemeinen Funktionen zu entkoppeln, die auf sie angewendet werden (wie Sortieren und Verketten). Abstrakte Darstellungen effizienter Algorithmen und Datenstrukturen führen zu einem aussagekräftigeren Code, da deutlich weniger geraten wurde, wie eine Funktion, die mit einem bestimmten Datenelement arbeitet, am besten implementiert werden kann. Die C-Makros entsprachen weitaus mehr dem, was man normalerweise in Lisp-Makros sieht, da sie eine Möglichkeit bieten, die Sprache mit Inline-Code zu "erweitern". Das Coole ist, dass die C ++ Standard Library die Funktionalität von Vorlagen erweitert hat, um die große Mehrheit dessen abzudecken, wofür wir #define in C verwenden.

Marc
quelle