Bedingte Kompilierung mit Templates
-
doch doch - ich lese sie. danke hierfür schonmal.
Auch mit der Deklaration der paramter im kontstruktor mit:
Matrix.imp
#include "Impl_Env.h" //C/C++ includings #include <string> #include <stdlib.h> #include <sstream> #include <iostream> template <class T_Field> Matrix<T_Field>::Matrix(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows) { num_procs = 0; my_id = 0; Env_Stats(num_procs, my_id); std::cout << num_procs << std::endl; }
bleibt der fehler bestehen.
Deinen Post mit der auslagerung in einen header und einer spezialisierung versthe ich leider nicht. Ich habe doch Env_Stats in einem Header und brauche keine spezialisierung in einer cpp datei da Env_Stats doch nicht template-abhängig ist...??
-
Du hast nicht verstanden, warum normalerweise C++ Programme in Header und cpp Dateien aufgetrennt werden.
http://gpwiki.org/index.php/Programming_Techniques:C/CPP_Header_File_Convention
http://stackoverflow.com/questions/333889/in-c-why-have-header-files-and-cpp-files
-
Vielen Dank für die Links - ich habe sie gelesen und versuche jetzt den Transfer der mich nicht leicht fällt....
-
Ich steh auf dem Schlauch.
Ich versuche es im Moment mit der auslagerung in cpp dateien so:main.cpp
#include "Impl_Env.h" #include "Matrix.h" #include <iostream> #include <stdexcept> int main(int argc, char *argv[]) { int num_procs, my_id; int a = 9; int b = 8; Matrix<int>* A_REAL = new Matrix<int>(ENV_WORLD,a,b); #ifdef ENV_MPI std::cout << "PARALLEL" << std::endl; #else std::cout << "SERIAL" << std::endl; #endif }
Impl_Env.h
#ifndef IMPL_ENV_H #define IMPL_ENV_H #ifdef ENV_MPI # include <mpi.h> #define ENV_WORLD void* # include "parallel/Impl_MPI.cpp" #else #define ENV_WORLD void* # include "serial/Impl_SERIAL.cpp" #endif #endif
Matrix.h
#ifndef GUARD_MATRIX_H #define GUARD_MATRIX_H #include "Impl_Env.h" #include "test.h" template <class T_Field> class Matrix { public: /// Empty Constructor Matrix<T_Field>(){ num_procs = 0; my_id = 0;}; Matrix<T_Field>(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows); ~Matrix<T_Field>(){}; int num_procs, my_id; }; #include "Matrix.imp" #endif
Matrix.imp
#include "Impl_Env.h" //C/C++ includings #include <string> #include <stdlib.h> #include <sstream> #include <iostream> template <class T_Field> Matrix<T_Field>::Matrix(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows) { num_procs = 0; my_id = 0; Env_Stats(world_m,num_procs, my_id); std::cout << num_procs << std::endl; }
test.h
#ifndef TEST_H #define TEST_H inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) { // num_procs = 2; }; #endif
serial/Impl_SERIAL.cpp
#include "test.h" inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) { num_procs = 2; }
parallel/Impl_MPI.cpp
#include "test.h" inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) { num_procs = 3; }
Als fehlermeldung kommt:
test.h: In function »void Env_Stats(void*, int&, int&)«: test.h:6: Fehler: redefinition of »void Env_Stats(void*, int&, int&)« parallel/Impl_MPI.cpp:5: Fehler: »void Env_Stats(void*, int&, int&)« wurde vorher hier definiert
Allerdings verstehe ich (noch) nicht wo eine redefenition statt findet...
-
test.h
#ifndef TEST_H #define TEST_H inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id); #endif
-
ah sorry - hab vergessen die geschweiften klammern wegzubringen beim header...
-
Ok - damit scheint der obige fehler beseitigt zu sein.
Allerdings bekomme ich jetzt eine Reihe weiterer Fehler. Warum inline nicht mehr erlaubt ist verstehe ich nicht - warum plötzlich das void nicht erlaubt ist verstehe ich auch nicht:#include "Impl_Env.h" #include "Matrix.h" #include <iostream> #include <stdexcept> int main(int argc, char *argv[]) { int num_procs, my_id; int a = 9; int b = 8; Matrix<int>* A_REAL = new Matrix<int>(ENV_WORLD,a,b); #ifdef ENV_MPI std::cout << "PARALLEL" << std::endl; #else std::cout << "SERIAL" << std::endl; #endif }
//Impl_Env.h
#ifndef IMPL_ENV_H #define IMPL_ENV_H #ifdef ENV_MPI # include <mpi.h> #define ENV_WORLD NULL # include "parallel/Impl_MPI.cpp" #else #define ENV_WORLD NULL # include "serial/Impl_SERIAL.cpp" #endif #endif
Matrix.h
#ifndef GUARD_MATRIX_H #define GUARD_MATRIX_H #include "Impl_Env.h" #include "test.h" template <class T_Field> class Matrix { public: /// Empty Constructor Matrix<T_Field>(){ num_procs = 0; my_id = 0;}; Matrix<T_Field>(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows); ~Matrix<T_Field>(){}; int num_procs, my_id; }; #include "Matrix.imp" #endif
Matrix.imp
#include "Impl_Env.h" //C/C++ includings #include <string> #include <stdlib.h> #include <sstream> #include <iostream> template <class T_Field> Matrix<T_Field>::Matrix(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows) { num_procs = 0; my_id = 0; Env_Stats(world_m,num_procs, my_id); std::cout << num_procs << std::endl; }
serial/Impl_Serial.cpp
#include "../test.h" inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) { num_procs = 2; }
parallel/Impl_MPI.cpp
#include "../test.h" inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) { num_procs = 3; }
test.h
#ifndef TEST_H #define TEST_H #include "Impl_Env.h" inline void Env_Stats(ENV_WORLD world, int& num_procs, int& my_id); #endif
-
Poste mal die Fehlermeldung. Habe keine Lust so viele Dateien zu kopieren.
edit: Mir scheint da aber auf den ersten Blick was mit den includes nicht zu stimmen. matrix.impl benutzt Sachen aus matrix.h ohne diese zu kennen.
-
sorry hab ich vorhin vergessen...
parallel/../test.h:7: Fehler: Variable oder Feld »Env_Stats« als »void« deklariert parallel/../test.h:7: Fehler: »NULL« wurde in diesem Gültigkeitsbereich nicht definiert parallel/../test.h:7: Fehler: expected primary-expression before »int« parallel/../test.h:7: Fehler: expected primary-expression before »int« parallel/../test.h:7: Fehler: initializer Ausdrucksliste als zusammengesetzten Ausdruck behandelt parallel/Impl_MPI.cpp:4: Fehler: Variable oder Feld »Env_Stats« als »void« deklariert parallel/Impl_MPI.cpp:4: Fehler: »Env_Stats« als »inline« variable deklariert parallel/Impl_MPI.cpp:4: Fehler: redefinition of »int Env_Stats« parallel/../test.h:7: Fehler: »int Env_Stats« wurde vorher hier definiert parallel/Impl_MPI.cpp:4: Fehler: »NULL« wurde in diesem Gültigkeitsbereich nicht definiert parallel/Impl_MPI.cpp:4: Fehler: expected primary-expression before »int« parallel/Impl_MPI.cpp:4: Fehler: expected primary-expression before »int« Matrix.h:16: Fehler: expected `)' before »world_m« Matrix.imp:10: Fehler: expected constructor, destructor, or type conversion before »(« token main.cpp: In function »int main(int, char**)«: main.cpp:14: Fehler: keine passende Funktion für Aufruf von »Matrix<int>::Matrix(NULL, int&, int&)«
-
Uffob schrieb:
sorry hab ich vorhin vergessen...
parallel/../test.h:7: Fehler: Variable oder Feld »Env_Stats« als »void« deklariert parallel/../test.h:7: Fehler: »NULL« wurde in diesem Gültigkeitsbereich nicht definiert parallel/../test.h:7: Fehler: expected primary-expression before »int« parallel/../test.h:7: Fehler: expected primary-expression before »int« parallel/../test.h:7: Fehler: initializer Ausdrucksliste als zusammengesetzten Ausdruck behandelt parallel/Impl_MPI.cpp:4: Fehler: Variable oder Feld »Env_Stats« als »void« deklariert parallel/Impl_MPI.cpp:4: Fehler: »Env_Stats« als »inline« variable deklariert parallel/Impl_MPI.cpp:4: Fehler: redefinition of »int Env_Stats« parallel/../test.h:7: Fehler: »int Env_Stats« wurde vorher hier definiert parallel/Impl_MPI.cpp:4: Fehler: »NULL« wurde in diesem Gültigkeitsbereich nicht definiert parallel/Impl_MPI.cpp:4: Fehler: expected primary-expression before »int« parallel/Impl_MPI.cpp:4: Fehler: expected primary-expression before »int« Matrix.h:16: Fehler: expected `)' before »world_m« Matrix.imp:10: Fehler: expected constructor, destructor, or type conversion before »(« token main.cpp: In function »int main(int, char**)«: main.cpp:14: Fehler: keine passende Funktion für Aufruf von »Matrix<int>::Matrix(NULL, int&, int&)«
Du hast eine zyklische Abhängigkeit: test.h benutzt Impl_env.h benutzt Impl_XXX.cpp benutzt test.h. Das fliegt dir um die Ohren.
Ich habe in meinem letzten Beitrag übrigens nochmal eine kleine Anmerkung reingeschrieben, während du die Fehlermeldung gepostet hast.
-
Naja, alles includiert alles wild durcheinander und ohne Plan. Normalerweise includiert man auch kein cpp-Dateien ... Du solltest dir ein gutes Tutorial suchen, das die Aufteilung von Header und cpp-Dateien behandelt.
#define ENV_WORLD NULL ... Env_Stats(ENV_WORLD world, int& num_procs, int& my_id) ... Matrix<T_Field>::Matrix(ENV_WORLD world_m, const int nbr_cols, const int nbr_rows)
ENV_WORLD ist kein Datentyp.
Mitlerweile wuerde ich dir zu einem besseren C++ Buch/Tutorial raten.
-
Normalerweise includiert man auch kein cpp-Dateien
hmm...danke für den hinweis. Ich möchte aber als Anfänger darauf hinweisen in der Hoffnung dass mir jemand bei diesem etwas speziellerem problem hilft:
a) ich wüsste im moment nicht wie denn anstatt der .cpp dateien dann wieder header inkludieren sollte.
b) wie sieht es denn aus wenn die methoden in Impl_SERIAL.cpp und IMPL_MPI.h templatebasiert sein sollen? Oder gar spezialisierungen auftreten. Dann wirds ja nochmals komplizierter...kann ich damit dann Leben mit dem EIN-Header ansatz den Knivil vorschlägt?
Falls jemand Lust/Zeit hat würde ich mich über die Veränderung meines Minimalbeispieles freuen. Danke euch....
-
Mitlerweile wuerde ich dir zu einem besseren C++ Buch/Tutorial raten.
hast du ein gutes buch/tutorial? Ich suche schon lange eines...
-
Du kannst mal in die FAQ - C++ des Forums schauen.
-
Ich habe jetzt nur die letzten paar Beiträge hier im Thread gelesen, daher weiß ich nicht, ob ich jetzt irgendwas wiederhole:
Uffob schrieb:
a) ich wüsste im moment nicht wie denn anstatt der .cpp dateien dann wieder header inkludieren sollte.
Die test.h ist doch anscheinend der Header der zu den Impl_XXX.cpp gehört. Also dort wo diese eingebunden werden, nimmst du test.h
b) wie sieht es denn aus wenn die methoden in Impl_SERIAL.cpp und IMPL_MPI.h templatebasiert sein sollen? Oder gar spezialisierungen auftreten. Dann wirds ja nochmals komplizierter...kann ich damit dann Leben mit dem EIN-Header ansatz den Knivil vorschlägt?
Ja, dann wird das mit einem gemeinsamen Header für beide unmöglich. Dann müssen die Templatedefinitionen in einen Header und entsprechende #ifdefs drumherum.
-
danke aber ich verstehe die antwort nicht.
Die test.h ist doch anscheinend der Header der zu den Impl_XXX.cpp gehört. Also dort wo diese eingebunden werden, nimmst du test.h
ich kann doch nicht schreiben:
Impl_Env.h#ifndef IMPL_ENV_H #define IMPL_ENV_H #ifdef ENV_MPI # include <mpi.h> #define ENV_WORLD void* # include "test.h" #else #define ENV_WORLD void* # include "test.h" #endif #endif
und dann in einem header alle deklarationen haben und nirgendwo die Impl_.cpp einbinden. Oder meinst du dass dann in klassen oder dateien die spezifische Impl_.cpp datei eingebunden wird?
Das würde abe bedeuten sobald man eine neue implementierung hinzufügt muss man überall wieder das #include Impl_*.cpp anpassen. damit wäre ja die ganze idee die shade hatte in diesem Thread hatte:egal.
zu b).: Bist du sicher dass es keine Möglichkeit gibt? Was wäre denn eine Möglichkeit das zu bewerkstelligen? WIe geht man sonst vor wenn man eine reihe implementierungen hat? Es macht doch wenig sinn an jede stelle x mal ein #ifdef #elseif etc.... zu machen....??
-
Uffob schrieb:
ich kann doch nicht schreiben:
[...]
und dann in einem header alle deklarationen haben und nirgendwo die Impl_*.cpp einbinden.Doch? Das ist doch gerade das wozu Header da sind. Ich verstehe sowieso nicht, wieso du die ganze Zeit cpp Dateien einbinden willst.
Oder meinst du dass dann in klassen oder dateien die spezifische Impl_.cpp datei eingebunden wird?
Das würde abe bedeuten sobald man eine neue implementierung hinzufügt muss man überall wieder das #include Impl_.cpp anpassen. damit wäre ja die ganze idee die shade hatte in diesem Thread hatte [...] egal.Na eben nicht. Implementierung neu kompilieren, fertig. Das ist ja gerade das tolle an dem System.
zu b).: Bist du sicher dass es keine Möglichkeit gibt? Was wäre denn eine Möglichkeit das zu bewerkstelligen? WIe geht man sonst vor wenn man eine reihe implementierungen hat? Es macht doch wenig sinn an jede stelle x mal ein #ifdef #elseif etc.... zu machen....??
Du machst einmal einen #ifdef-Block um die verschiedenen Implementierungen und fertig. Das ist ja wohl nicht mehr Arbeit als du dir jetzt machst.