Template in Deklaration und Implementierung trennen
-
Hi,
ich lese zur Zeit das Buch "Modern C++-Design", welches mir schon mehrfach empfohlen wurde. Ich habe daher ein allgemeine Frage zu Templates:
Im Buch werden Templates fast an allen Stellen verwendet, was in meinem Code dazu führen würde, dass ich andauernd die Implementierungsdatei .cpp in der Headerdatei .h anbinden muss, da der Compiler (gcc) das wohl nicht anders hingekommt (oder irre ich hier schon?).
Das ganze führt dann dazu, das sich in meinem Programm Headerdateien in irgendeiner Form gegenseitig einbinden. Dadurch kann mein Projekt nicht mehr compiliert werden, weil zig Fehlermeldungen kommen, das er dies und jenes nicht finden kann.
Gibt es etwas sinnvolles, was man dagegen tun kann?Gruß Christian
-
Wenn dein Compiler das Schlüsselwort "export" nicht unterstützt, nicht so
richtig. Du kannst prüfen ob du nicht an der einen oder anderen Stellen mit
Forward-Deklarationen arbeiten kannst.
Aber da der g++ besser mit LOKI klar kommt als der VC6, hast du vielleicht Fehler im Design, wenn du garnicht weiterkommst.mfg JJ
-
Hi John,
ich kann dir mal ein fiktives Bsp geben:
Wir haben 2 Template-Klassen Foo und Bar. Die Dateien heißen also foo.h, foo.cpp und bar.h bzw. bar.cpp.
in foo.h steht #include "foo.cpp",
in foo.cpp steht #include "bar.h",
in bar.h steht #include "bar.cpp" und
in bar.cpp steht #include "foo.h"Ich bin bisher ein bissel ratlos...
Forward Deklarationen werden hier wohl nichts bringen, wenn foo.cpp und bar.cpp beispielsweise Methoden des jeweils anderen aufrufen.
Was heißt eigentlich "LOKI"?Gruß Christian
-
1. loki ist eine bibliothek für solche sachen, wie sie im buch,welches du liest, vorgestellt werden.
in foo.h steht #include "foo.cpp",//OH MEIN GOTT in foo.cpp steht #include "bar.h", in bar.h steht #include "bar.cpp" und//OH MEIN GOTT in bar.cpp steht #include "foo.h"
OH MEIN GOTT= ERHEBLICHE Designschwäche. sowas macht man nicht. das ist weder sinnvoll noch irgendwie programmfördernd.
//edit ansonsten gibt es viele möglichkeiten, die abhängigkeiten zwischen foo und bar zu minimieren:
1. vorwärtsdeklaration: wenn man in foo nur referenzen/zeiger auf bar braucht, dann ist das die schönste möglichkeit.
2. pimpl idiom. Eine konsiquente weiterentwicklung der vorwärtsdeklaration, fällt aber mit templates manchmal weg.
3. template parameter: nehmen wir an, foo braucht bar. bar ist aber gewissermaßen austauschbar. dh, es kann situationen geben, in denen eine andere Klasse, die sich zwar wie bar verhält, aber nicht bar ist, nützlicher ist. in dem fall kann man dann die abhängigkeit in einen template parameter legen, und hat die direkte abhängigkeit zwischen foo und bar eliminiert.
-
otze schrieb:
OH MEIN GOTT= ERHEBLICHE Designschwäche. sowas macht man nicht. das ist weder sinnvoll noch irgendwie programmfördernd.
Du hast mitbekommen, dass es um Templates geht?
Man sollte nur die Implementierungsdatei nicht gerade .cpp nennen. damit man nicht in Versuchung kommt, sie einzeln zu kompilieren.
-
Du hast mitbekommen, dass es um Templates geht?
ja. und auch, wenn es im ersten moment "toll ist" das mit nem include nachreichen zu können,sowas ist extremst unschön zu lesen:
template<class T,class policy1,class policy2,class policy3> struct Foo{ template<class U> void bar(U); }; //in der INL/CPP/was auch immer template<class T,class policy1,class policy2,class policy3> template<class U> void Foo<T,policy1,policy2,policy3>::Bar<U>(U p){ //... }
nimmt man nun worst case, und zwar eine nested template Klasse innerhalb von foo, dann bin ich mir sicher, dass das kein schwein mehr lesen will. Das wette ich mit dir.
-
otze schrieb:
nimmt man nun worst case, und zwar eine nested template Klasse innerhalb von foo, dann bin ich mir sicher, dass das kein schwein mehr lesen will. Das wette ich mit dir.
Keine Frage, das ist hässlich.
Aber du sprachst ursprünglich nicht von "extremst unschön zu lesen", sondern von "OH MEIN GOTT= ERHEBLICHE Designschwäche". Ist das bei dir gleichbedeutend?
-
ja. ein gutes design muss lesbar sein,da sonst unwartbar(sorry, war gestern schon etwas müde, kam von ner lan wieder, deshalb ists vielleicht falsch rübergekommen :))
-
Sorry ich bin jetzt ein bissel durcheinander.
Das z.B. in foo.h steht #include "foo.cpp" finde ich ja auch unschön, aber
sonst nörgelt doch der Compiler. Also bei "normalen Klassen" muss ich das ja nicht machen, aber bei Template-Klassen leider schon. Oder kommt man irgendwie mit export und extern drumherum?
Ich sehe leider nicht wie mir Forward-Deklarationen weiterhelfen können
Wenn z.B. in foo.cpp Methoden von der Klasse Bar aufgerufen werden, dann muss ich doch die bar.h einbinden.
Mit dem Buch bin ich noch ganz am Anfang, da wo die Policy-classes erst vorgestellt werden. Das Wort Loki fiel erst ein einziges mal...Gruß Christian
-
Ich hoffe, ich habe euch nicht mit meinen dämlichen Fragen vergrault.
Aber es ist mir wirklich sehr wichtig zu wissen, wie man die oben beschriebene Abhängigkeit compiliert bekommt.Gruß Christian
-
ohne wenisgstens etwas code, kann man dir garnicht helfen,da man verschiedene abhängigkeiten verschieden auflösen kann. Und Kristallkugeln werden hier nicht benutzt.
-
Also gibt es sozusagen keine Standard-Methode die immer klappt, sondern man muss von Fall zu Fall sehen was man tuen kann, richtig?
Ohne Template-Klassen gibt es ja überhaupt keine Problem damit.
Mal angenommen man könnte export und so verwenden. Dann dürfte es doch keine Probleme mehr mit den Abhängigkeiten geben, oder?
Unterstützt das überhaupt irgendein Compiler?Gruß Christian
-
wozu hast du überhaupt die trennung .h // .cpp
mach doch alles in der .h ist IMHO auch die einzige möglichkeit,
zB bei mir ( ich benutzt den BCB6.0 ), wenn ich die implimentation einer template-klasse in die .cpp packe, dann findet der linker die implementation nicht mehr, da kann ich machen was ich will. ich nehme an, das du das gleiche prob hast, weil du die .cpp direkt includest.
-
Oh jetzt bin ich aber ein bisschen geschockt.
In allen C++ Büchern die ich gelesen hatte, stand, das man Deklaration und Implementierung sorgfältig trennen sollte. Auch UML-Tools wie z.B. Umbrello generieren automatisch Projekte nach diesem Paradigma.
Ich meine, ich könnte jetzt auch alles in einer Datei packen. Allerdings müsste ich dann jedesmal wenn ich in einer Datei X eine Klasse in Datei Y verwenden möchte, die komplette Deklaration voranstellen.
Oder gibt es da geeignete Techniken?Gespannte Grüße
Christian
-
der einzige compiler, der templateimplementationen ind ie cpp auslagern kann, ist der comeau, da er der einzige compiler ist, der export unterstützt
-
Kann du den comeau empfehlen?
Und weißt du ob solche Erweiterungen bei einer neuen Version vom g++ geplant sind?
-
das sit keine "erweiterung" das ist standard. und ja, der comeau ist uneingeschränkt zu empfehlen, kostet aber 50$
-
man sollte das schon trennen aber was nicht möglich ist, ist nicht möglich
das ist eigentlich echt komisch das sowas nur der Comeau unterstützt
-
Gibt es vom Comeau eine Trialversion?
-
nur eine internetversion für kleine sachen^^