In meiner vorherigen Frage habe ich gefragt ist rekursive explizite Template-Instanziierung möglich . Ich sah, dass es tatsächlich möglich ist; Diese Instanziierung erweist sich jedoch nur lokal als effektiv, die Symbole der rekursiv instanziierten Vorlage werden nicht in die Objektdatei exportiert und erscheinen daher nicht in der (gemeinsamen) Bibliothek. Also frage ich hier genauer nach wie in meinem vorherigen Beitrag:
Gegeben eine Vorlage wie
%Vor%Diese Vorlage kann explizit wie
instanziiert werden %Vor% exportiert die Symbole von Point<0>
, ..., Point<3>
in die Objektdatei der aktuellen Übersetzungseinheit. Anstatt jedes Template individuell wie oben beschrieben zu instantiieren, möchte ich diese rekursiv mit nur einem Aufruf instanziieren.
Jede Lösung, die dies erreicht, ist gut, sei es im Stil der Template-Metaprogrammierung, über eine Hilfsklasse wie
%Vor%oder über den Präprozessor. Hier schaute ich in die Boost-Präprozessor-Bibliothek, die einige Schleifenkonstrukte zu haben scheint. Allerdings habe ich nie die Boost-Preprozessor-Bibliothek benutzt (jeder Rat wird geschätzt), aber auf den ersten Blick bin ich skeptisch, ob die Loops zusammen mit einer expliziten Template-Instantiierung verwendet werden können.
Jeder Rat, auch eine Erklärung, warum es unmöglich ist, was ich erreichen möchte, wird geschätzt.
Tatsächlich bin ich daran interessiert, dies für Klassen mit mehreren Template-Parametern wie Node<int i1,int i2,int i3>
für alle Kombinationen von i1, i2, i3 in {0,1,2,3} zu verallgemeinern. Aber ich hoffe, dass ich diesen zweiten Teil selbst erarbeiten kann. Wie immer möchte ich die expliziten Instanziierungen verwenden, um die Kompilierzeiten zu beschleunigen, indem ich nur die Vorlagen in einer Übersetzungseinheit definiere. Daher brauche ich die Methoden für die Vorlage, um sie in die Objektdatei zu exportieren.
Ich hoffe auf eine Compiler-unabhängige Lösung, aber wenn das nicht möglich ist, brauche ich es für Linux mit g ++ / clang.
Siehe unten für einen Überblick über die Lösungen, die ich bekommen habe, und die endgültigen Lösungen, die ich daraus gemacht habe.
Scheint wie ein Job für Boost.Preprocessor :
%Vor%Natürlich können Sie dies in ein anderes Makro einbetten, um es besser aussehen zu lassen:
%Vor%Siehe die von Luc Touraille vorgeschlagene Lösung
%Vor%Siehe die Lösung und die sehr gute Erklärung von phresnel unten. Dies klingt nach dem bevorzugten Ansatz. Leider kann explizite Instanziierung nur auf globaler Ebene (eine Sprachbeschränkung) verwendet werden und kann daher nicht rekursiv verwendet werden. Wenn die Instanziierung implizit durchgeführt wird (siehe meine vorherige Frage), dann werden nur die Symbole definiert (und somit in die Objektdatei exportiert), die tatsächlich verwendet werden, dh Sie müssen jedes Symbol der Klasse einmal (mit einem Dummy) definieren / p>
Dies ist kein sehr netter Ansatz, aber es vermeidet möglicherweise unangenehme Probleme (und Portabilitätsprobleme) der Präprozessor-Lösungen.
Schließlich tauchte ich auch tiefer in die Boost-Vorverarbeitungsbibliothek ein und versuchte, das Ergebnis zu erweitern, um Instanzen der Form zu erstellen
%Vor% Also eine Vorlage Node<Scalar, pdim, ldim>
mit Scalar
und arithmetische% pdim
und ganze Zahl und ldim <= pdim
eine andere ganze Zahl.
Ich konnte den Ansatz nur um BOOST_PP_REPEAT
für Vorlagen mit zwei Argumenten erweitern, da BOOST_PP_REPEAT
derzeit nur 3 Ebenen tief verschachtelt sein kann. Zwei Ebenen für die Template-Parameter und eine Ebene für BOOST_PP_ENUM
war das Maximum, das ich mit dieser Technik erreichen konnte. Es ist flexibler, die Dateiiteration -Technik zu verwenden, die bis zu 5 Ebenen.
Diesen Code konnte ich mit dem Code
erzeugen %Vor%Die vier Instanzen für die Point-Klasse in der Frage können über
generiert werden %Vor%Beide Methoden werden mit der Datei "util / templateRecInstant.h" mit dem Inhalt
erreicht %Vor%Wenn Sie auf dieses Problem stoßen, können Sie den obigen Code verwenden. Um diesen Code zu generieren, habe ich 1 als Referenz verwendet.
> Das Problem, dem Sie gegenüberstehen, ist: Tatsächlich wird RecursiveInstantiate
vollständig instanziiert. Aber die "eingeschlossenen" Typen werden nur in dem Maße instanziiert, wie Sie mit in RecursiveInstantiate
instanziiert haben. Wenn Sie beispielsweise keine Funktion Point::xxx
aufrufen, wird xxx
nicht instanziiert. Dies ist das übliche Verhalten. Sie benötigen eine Syntax für die explizite Instanziierung innerhalb von Klassen oder Funktionen.
Ich denke, Sie können keine vollständige Instanziierung für alle enthaltenen Referenzen durchführen, Sie können dies explizit instanziieren, aber nicht implizit.
z. B.
%Vor%dann
%Vor% In der Funktion instantiate
würden Sie sich auf alles beziehen, was exportiert werden soll.
Sie müssen den besten Kompromiss abwägen, möglicherweise ist mein Ansatz der kürzeste, möglicherweise manuelle Typdown ( template class Foo<0>; template class Foo<1> ...
) ist kürzer, weil Sie viele Mitgliedsfunktionen haben, möglicherweise halten Sie den BOOST-Weg für tragbar genug, selbst wenn der Standard dies tut nicht genehmigen.
Es wäre interessant, wenn es eine Syntax für explizite Instanziierung in nicht-globalen Kontexten geben würde.
Tags und Links c++ templates boost-preprocessor