Frage

Ich verwende eine Bibliothek, die fast ausschließlich aus Templat Klassen und Funktionen in Header-Dateien , wie folgt zusammen:

// foo.h
template<class T>
class Foo {
  Foo(){}
  void computeXYZ() { /* heavy code */ }
};
template<class T>
void processFoo(const Foo<T>& foo) { /* more heavy code */ }

Nun, das ist schlecht, weil kompilieren Zeiten sind unerträglich , wenn ich gehöre einer dieser Header-Dateien (und ich bin tatsächlich viele von ihnen in jedem meiner Kompilierungseinheiten).

Da als Template-Parameter nur ich eine oder zwei Arten verwende sowieso Ich plane, für jede Bibliothek Header-Datei zu erstellen, eine Datei, die nur Erklärungen enthält, ohne den schweren Code wie folgt:

// NEW: fwd-foo.h
template<class T>
class Foo {
  Foo();
  void computeXYZ();
};
template<class T>
void processFoo(const Foo<T>& foo);

Und dann eine Datei, die alle Instanzen erstellt, die ich benötigen. Diese Datei kann werden separat einmal kompiliert und für alle :

// NEW: foo.cpp
#include "foo.h"
template class Foo<int>;
template class Foo<double>;
template void processFoo(const Foo<int>& foo);
template void processFoo(const Foo<double>& foo);

Jetzt kann ich nur schließen in meinem Code fwd-foo.h und haben kurze Zeiten kompilieren. Ich werde verknüpfen gegen foo.o am Ende.

Der Nachteil ist natürlich, dass ich diese neue fwd-foo.h und foo.cpp-Dateien selbst erstellen haben. Und natürlich ist es ein Wartungsproblem: Wenn eine neue Version der Bibliothek freigegeben wird, ich habe sie auf die neue Version anzupassen. Gibt es noch andere Nachteile?

Und meine Hauptfrage ist:

Gibt es eine Chance, dass ich diese neue Dateien erstellen kann, insbesondere fwd-foo.h, automatisch aus dem ursprünglichen foo.h? Ich habe dies für viele Bibliothek Header-Dateien zu tun (vielleicht 20 oder so) und eine automatische Lösung wäre besonders am besten sein, falls eine neue Version der Bibliothek freigegeben wird, und ich habe dies mit der neuen Version wieder zu tun. Sind irgendwelche Werkzeuge für diese Aufgabe zur Verfügung?

EDIT:

Weitere Frage: Wie kann das neu unterstützte extern Stichwort helfen Sie mir in diesem Fall

War es hilfreich?

Lösung

Wir verwenden LZZ , die eine einzelne Datei in einen separaten Header und Übersetzungseinheit teilt aus. Standardmäßig wäre es normalerweise die Vorlage Definitionen in den Header setzen jedoch zu können, geben Sie an, dass Sie dies nicht wollen passieren.

Um Ihnen zu zeigen, wie Sie es sich anschauen sollten Sie Folgendes ein:

// t.cc
#include "b.h"
#include "c.h"

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

Nehmen Sie die obige Datei und kopieren Sie sie in ‚t.lzz‘ Datei. Legen Sie alle #include Richtlinien in separate $ hdr und $ src Blöcke nach Bedarf an:

// t.lzz
$hdr
#include "b.h"
$end

$src
#include "c.h"
$end

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

Nun endlich laufen LZZ über die Datei angeben, dass sie die Vorlage Definitionen in der Quelldatei platziert. Sie können entweder tun dies mit einem $ Pragma in der Quelldatei, oder Sie können die Befehlszeilenoption „-ts“ verwenden:

Das in den folgenden Dateien führen wird generiert:

// t.h
//

#ifndef LZZ_t_h
#define LZZ_t_h
#include "b.h"
#undef LZZ_INLINE
#ifdef LZZ_ENABLE_INLINE
#define LZZ_INLINE inline
#else
#define LZZ_INLINE       
#endif
template <typename T>
class A
{
  void foo ();
  B b;
};
#undef LZZ_INLINE
#endif

Und:

// t.cpp
//

#include "t.h"
#include "c.h"
#define LZZ_INLINE inline
template <typename T>
void A <T>::foo ()
          {
    C c;
    c.foo ();
    b.foo ();
  }
#undef LZZ_INLINE

Sie können diese dann durch einige grep / sed Befehle ausführen, um die LZZ Helfer Makros zu entfernen.

Andere Tipps

Versuchen Sie vorkompilierte Header verwenden. Ich weiß, GCC und MSVC diese Funktion unterstützen. Die Verwendung ist vender spezifische, though.

Ich habe eine ganze Weile auf dem gleichen Problem gearbeitet, jetzt. In der Lösung Sie vorschlagen, definieren Sie Ihre Template-Klassen zweimal. Es wird in Ordnung sein, wenn es das gleiche Material definiert (in der gleichen Reihenfolge), aber Sie sind verpflichtet, Probleme haben, früher oder später.

Was ich habe kommen mit ist das Problem umgekehrt zu betrachten. Solange Sie Ihre Implementierung nicht spezialisiert sind, funktioniert es ordnungsgemäß.

Es werden zwei Makros, die Vorlage Argumente in Implementierungsdatei aktualisieren avois mit (Vorsicht, obwohl, wenn Sie Standardvorlage Argumente zur Klasse hinzufügen möchten).

// foo.h
#define FOO_TEMPLATE template<typename T>
#define FOO_CLASS Foo<T>

FOO_TEMPLATE
class Foo {
  Foo();
  void computeXYZ();
};

// foo_impl.h
#include "foo.h"
FOO_TEMPLATE
FOO_CLASS::Foo(){}

FOO_TEMPLATE
void FOO_CLASS::computeXYZ() { /* heavy code */ }

Auf diese Weise arbeiten Sie im Wesentlichen auf die gleiche Weise mit Nicht-Template-Klassen zu tun (Sie die gleiche Sache mit Template-Funktionen zu tun, natürlich).

EDIT: über das Schlüsselwort extern in C ++ 0x

Ich glaube, das Schlüsselwort extern in C ++ 0x helfen, aber es wird nicht alles auf magische Weise lösen!

diesem Artikel ,

  

Externe Vorlagen

     

Jedes Modul, das eine instanziiert   Vorlage erstellt im Wesentlichen eine Kopie   es in dem Objektcode. Dann geht es nach oben   an den Linker aller die Verfügungs   redundanter Objektcode in dem allerletzten   Stufe verlangsamt somit die kritische   edit-Kompilierung-link-Zyklus, der nach oben macht   ein Tag Programmierer (oder manchmal   Wachträume). Kurzzuschließen dieser   Objektcode garbage collection, a   Anzahl der Compiler-Anbieter haben   bereits implementiert ein Schlüsselwort extern   das kann vor Vorlagen gehen.   Dies ist ein Fall, der Normung   kodifiziert bestehende Industriepraxis   (Wortspiel beabsichtigt). In der Praxis ist dies   umgesetzt durch eine Mitteilung an das Senden   Compiler grundsätzlich „nicht instanziiert   das hier ":

extern template class std::vector;

C ++ 0x Ihre Kompilierung Probleme mit externen Vorlagen beheben. Ich weiß nicht, eine automatische Art und Weise zu tun, was Sie fragen, though.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top