erzeugen einer static lib mit Vererbung und template
-
hallo zusammen,
ich habe ein kleines Problem, das vermutlich schon oft behandelt wurde ... ich habe es aber bis jetzt noch nicht gefunden
Ich habe 2 Klassen (A und B mit B erbt von A) und beides sind Template Klassen. Nun will ich daraus eine static lib machen und sie in einem Programm "test.cpp" einfügen.
Nun sagt mit aber der Linker ... denke ich ... das er die Klassen nicht findet. Könnt ihr mir da Helfen ?
A.cpp und A.h
//A.h #ifndef __A_H__ #define __A_H__ template<class T> class A{ public: T get(); protected: T value; }; #endif // __A_H__ //A.cpp #include "A.h" template<class T> T A<T>::get() { return value; }
B.cpp und B.h
//B.h //B.cpp #include "B.h" #ifndef __B_H__ #define __B_H__ #include "A.h" template<class T> class B: public A<T>{ public: B(T value); private: using A<T>::value; }; #endif // __B_H__ template<class T> B<T>::B(T value) { this->value = value; }
Erzeugen der static lib
g++ -c *.cpp && ar rcs testbib.a *.o
Test.cpp
#include "B.h" #include <iostream> int main(){ auto test = new B<int>(5); std::cout<<test->get()<<std::endl; }
Error
/usr/bin/ld: ./build/Debug/test.o: in function `main': /media/lukas/Tausch/Arbeit/libs/src/Communicator/test_programm/test.cpp:5: undefined reference to `B<int>::B(int)' /usr/bin/ld: /media/lukas/Tausch/Arbeit/libs/src/Communicator/test_programm/test.cpp:6: undefined reference to `A<int>::get()' collect2: error: ld returned 1 exit status Der Terminalprozess "/bin/bash '-c', '/usr/bin/g++ -Wall -Wextra -Wpedantic --std=c++20 -g3 -O0 -c test.cpp -o ./build/Debug/test.o && /usr/bin/g++ -Wall -Wextra -Wpedantic --std=c++20 -g3 -O0 ./build/Debug/test.o -o ./build/Debug/outDebug -lprotobuf -lpthread -L. -l:testbib.a'" wurde mit folgendem Exitcode beendet: 1.
Ich würde mich unglaublich freuen wenn ihr mir hier helfen könntet . Irgendwas scheine ich da wohl zu übersehen
Cheers
EvD
-
Templates (außer konkrete Template-Instantiierungen) können nicht direkt in Libs einkompiliert werden, da diese ja nur Vorlagen sind und daher der Source-Code dafür benötigt wird.
Du mußt also den Code komplett in die Header-Dateien packen und diese der Anwendung zur Verfügung stellen.Ab C++20 kannst du jedoch die Templates in Module packen und diese weitergeben, s.a. Templates and Modules.
-
@Th69 kann man beim erzeugen einer library die Templates ersetzen lassen
Oder muss ich das händisch machen
-
@EvD sagte in erzeugen einer static lib mit Vererbung und template:
@Th69 kann man beim erzeugen einer library die Templates ersetzen lassen
Oder muss ich das händisch machenDiejenigen Template-Instanzen, die du innerhalb des Library-Codes (
.cpp
) verwendest, werden implizit instanziiert und Teil des Objekt-Codes (sprich Teil der - in deinem Fall - statischen Bibliothek).Wenn du bestimmte Kombinationen von Template-Parametern jedoch nicht in deinem
.cpp
-Code verwendest, aber dennoch möchtest, dass sie in die statische Bibliothek einkompiliert werden, dann kannst du (in der.cpp
) die Templates auch explizit instanziieren (vgl. Class template instantiation - Explicit instantiation)://A.cpp ... template class A<int>; template class A<bool>; template class A<double>;
Damit kann man auch die Template-Implementierung (z.B.
A<T>::get() { ... }
) wie du das gemacht hast auch in die.cpp
-Datei packen*. Dann kann dann aber als Anwender nur diejenigen Template-Instanzen verwenden, die man in der.cpp
explizit hingeschrieben hat. Bei meinem Beispiel wäre in Code, der die Bibliothek verwendet, keinA<std::string>
oderA<MeineKlasse>
möglich. Möglicherweise will man aber auch gerade das.Bedenke aber, dass du so absolut jede Template-Instanz, die deine Bibliothek unterstützen soll, explizit hinschreiben musst. Wenn die Template-Implementierung im Header steht, ist das nicht notwendig (daher ist das oft die bessere Wahl und erstmal die "default"-Empfehlung).
* Das mit dem "Template-Implementierungen in den Header" ist kein ehernes Gesetz, wenn man weiss wie und warum man das macht - es vermeidet nur typische Anfängerfehler bei der Verwendung von Templates und ist in den allermeisten Fällen auch das, was man haben will.