ifdefs über virtuelle subklassen auslagern?
-
@Der Hüter der Zeit:
Sein aktuelles Problem ist, denke ich, dass er Code hat, der auf anderen Plattformen gar nicht gehen kann, weil es die Bibliothek dazu gar nicht gibt. Also hat er Funktionen, die es gar nicht gibt und dann reicht es nicht nur die template Instanzierung einzugrenzen.EDIT:
Nein. Doch das geht, wenn die Funktion ein template ist.
-
Also wir sollten nochmal klar stellen, was du überhaupt willst.
Grundsätzlich hast du ja 2 Probleme. Du willst eine gewisse Art von Polymorphie, also Teile des Code einfach austauschen ohne wirklich etwas ändern zu müssen. Meiner Meinung nacht ist statische Polymorphie (templates) immer noch die besser Alternative, weil du genau das willst.Das zweite Problem ist, dass gewisse Teile des Codes auf gewissen Platformen gar nicht funktionieren können, weil die Bibliotheken gar nicht vorhanden sind oder die Funktionen anderst heissen.
Die Verwirrung, die hier entstanden ist, ist imo darauf zurückzu schliessen, dass die beiden Probleme gemischt wurden. Darum nochmal differenziert betrachtet. Du willst das hier:
int main () { //manager<parallel> m; manager<sequential> m; m.general_stuff (); m.special (); }
Also sozuagen entweder ist ist der manager parallel oder sequentiell. Dafür eignet sich ja, wie schon gesehen das arbeiten mit einer Policy.
Jetzt kommt das zweite Problem. Es können nicht alle parallel arbeiten, also soll, wenn die erste Zeile aktiv ist ein Compilerfehler kommen, wenn es nicht unterstützt wird, oder?Also können wir das parallel einfach mit einem ifdef umschliessen:
struct sequential { void do_this_stuff () {} }; #ifdef DParallel struct parallel { void do_this_stuff () { MPI_Comm_Rank(); } }; #endif
Alternativ können wir da eine template Funktion benutzen, weil diese erst Kompiliert wird, wenn sie instanziert wird.
struct sequential { template <class T> void do_this_stuff () {} }; struct parallel { template <class T> void do_this_stuff () { MPI_Comm_Rank(); } };
Das führt aber dazu, dass wir hier eine template Funktion haben, wo es eigentlich gar nicht nötig ist. (Sprich beim Funktionsaufuf muss ein template Parameter angegeben werden).
Mir sind noch andere Möglichkeiten eingefallen, aber die zu diskutieren bringt es erst, wenn die Anforderungen klarer sind.
Nun kannst du ja auch die Auswahl in der main mit einem define lösen, wenn du möchtest.
-
Danke euch beiden. Ich habe im Moment die template-variante mit dem umschließenden #ifdef. Somit also 2 #ifdefs - einmal in der main zum instantiieren und einmal das umschließende #ifdef des parallelen anteiles. so kompiliert es jetzt. ich arbeite weiter und melde mich bei meiner nächsten frage danke euch !
-
Ok - also die template-variante und auch die idee mit einer abstrakten basisklasse für die beiden typen double und complex geht jetzt. Mein letztes Problem ist nun beides unter einen Hut zu bringen.
Dabei besteht mein Hauptproblem darin dass ich innerhalb der subklassen (double, complex) ebenfalls in den implementierten methoden auf die methoden aus sequential oder parallel zugreifen muss/will. also auch dort wieder auf ein objekt von manager zugreifen will sozusagen.
Ich wieß aber nicht wie ich das bewerkstelligen soll. ich kann ja nicht ein objekt manager an Base (von double und complex) übergeben weil damit müsste ja base templatebasiert sein. andererseits macht es wenig sinn innerhalb von manager die sachen anzulegen oder wäre das der richtige weg?
Oder anders gefragt:
Wie kann denn eine Methode einer Klasse (hier Complex z.B) die Subklasse von Base ist auf eine templatebasierte Methode einer anderen Klasse zugreifen?
-
Grundsätzlich hast du ja 2 Probleme. Du willst eine gewisse Art von Polymorphie, also Teile des Code einfach austauschen ohne wirklich etwas ändern zu müssen. Meiner Meinung nacht ist statische Polymorphie (templates) immer noch die besser Alternative, weil du genau das willst.
Warum hat man nicht 2 verschiedene Kompilierungseinheiten, die man entsprechend seinen Wuenschen zum gegeben Projekt dazu linkt. Gesteuert wird es halt ueber ein entsprechendes build script / system. Dann hat man weder stoerende ifdef's noch irgendwelche Templates. Der Code ist sauberer.
-
Warum hat man nicht 2 verschiedene Kompilierungseinheiten, die man entsprechend seinen Wuenschen zum gegeben Projekt dazu linkt. Gesteuert wird es halt ueber ein entsprechendes build script / system. Dann hat man weder stoerende ifdef's noch irgendwelche Templates. Der Code ist sauberer.
wie meinst dudas? hast du ein kleines minimalbeispiel?
-
Headerfile "do_something.h" der Funktion:
int do_something();
Implementationsdatei "do_something_parallel.cpp":
int do_something() { //do it parallel }
Implementationsdatei "do_something_sequential.cpp":
int do_something() { //do it sequential }
#include "do_something_parrallel.h" int main() { do_something(); }
So, nu wird abhaengig davon, was man will, entweder die parallele Variante kompiliert oder die sequentielle. Ein Beispiel ohne makefile mit gcc fuer die sequentielle Variante:
g++ do_something_sequential.cpp main.cpp
-
#include "do_something_parrallel.h" int main() { do_something(); }
fehlt da nicht was? so inkludierst du ja nur die parallele version. Oder muss man dann immer die main methode anpassen bevor kompiliert wird?
-
Ich denke, der include-Name ist nur unglücklich gewählt^^
Richtiger wäre vrmtl
#include "do_something.h"
dort muss ja an und für sich nur
void do_something();
drin stehen - die fkt wird dann einfach je nach der ausgewählten cpp-datei definiert...bb
-
aeh, ja, das meine ich.