Multiple Source Files: Templates
-
Wieso bekomme ich folgendes Bespielprogramm nicht zum laufen?
functions.cpp
#include "functions.h" template<typename T> bool print(T *t, unsigned int size) { for(int i = 0; size; ++i) { cout << t[i]; } }functions.h
#include <iostream> template<typename T> bool print(T *t, unsigned int size);main.cpp
#include "functions.h" int main() { print("Hallo!", 6); return 0; }Es kommt immer der Linker-Error "LNK2019: Verweis auf nicht aufgelöstes externes
Symbol ""bool __cdecl print<char const >(char const *,unsigned int)"
(??$CBD@@YA_NPBDI@Z)" in Funktion "_main".Was muss ich ändern damit es läuft?
-
Templates müssen bei nicht-C++11-Compilern immer in den Header-Dateien bzw. vor dem Linken bekannt sein. Wenn du dich etwas einliest, weißt du auch, warum das so ist.
-
Lösung:
Du musst function.cpp löschen undtemplate<typename T> bool print(T *t, unsigned int size) { for(int i = 0; size; ++i) { cout << t[i]; } }in den header verschieben. Deine function.h sollte dann so aussehen:
#ifndef FUNCTION_H // Include guards #define FUNCTION_H template<typename T> bool print(T *t, unsigned int size) { for(int i = 0; size; ++i) { cout << t[i]; } } #endifErklärung:
Templates sind nur Vorlagen für Funktionen, der Compiler generiert den Code der Funktion für erst, wenn das Template verwendet wird. Er setzt so zusagen den Typ ein (man nennt es auch "das Template wird instanziiert"). Um den Code der Funktion erstellen zu können, benötigt der Compiler jedoch den Rumpf der Funktion, also die Implementierung. (Da jede .cpp einzeln kompiliert wird, aber er erst in der main.cpp (oder wo das Template verwendet wird) weiß, für welche Typen das Template verwendet werden soll). Deswegen muss auch die Implementierung des Templates in den Header.
-
theliquidwave schrieb:
Templates müssen bei nicht-C++11-Compilern immer in den Header-Dateien bzw. vor dem Linken bekannt sein. Wenn du dich etwas einliest, weißt du auch, warum das so ist.
Das ist auch in C++11 nicht anders.
-
theliquidwave schrieb:
Templates müssen bei nicht-C++11-Compilern immer in den Header-Dateien bzw. vor dem Linken bekannt sein.
meinst du damit export oder ist das generell in C++11 so?
-
Skym0sh0 schrieb:
theliquidwave schrieb:
Templates müssen bei nicht-C++11-Compilern immer in den Header-Dateien bzw. vor dem Linken bekannt sein.
meinst du damit export oder ist das generell in C++11 so?
Ich denke er meint export, sonst ist in C++11 da auch nichts anders
-
OK, muss also alles in den Header rein...
-
Im Gegenteil, mit export wäre das vor C++ 11 zumindest theoretisch möglich gewesen (allerdings hat das praktisch kein Compiler jemals unterstützt). Da export mit C++ 11 abgeschafft wurde, geht es nun gar nicht mehr.
cppler schrieb:
OK, muss also alles in den Header rein...
ja
-
Naja es ginge mit extern, oder?
Allerdings auch nur wenn man alle Typen kennt mit denen das Template instanziert wird.EDIT: OK, extern braucht man gar nicht unbedingt, aber halt ne explizite Instanzierung in irgendeiner TU /EDIT
-
Naja, mit extern kann man aber, wie du selbst schon sagst, nur eine explizite Instanz eines template deklarieren. Du kannst nicht das template an sich irgendwo separat definieren.
-
@ccpler:
Mit einem kleinen Trick kannst du dir sogar die Übergabe der Größe sparen:template<typename T, int SIZE> bool print(T (&t)[SIZE])
-
@KasF: Geht leider nur mit statischen Arrays und so wie es da steht auch nur mit Strings, die nicht nullteminiert sind.
-
bstr schrieb:
@KasF: Geht leider nur mit statischen Arrays und so wie es da steht auch nur mit Strings, die nicht nullteminiert sind.
Das alles spielt keine Rolle. Jedes Array kann an diese Referenz gebunden werden. Egal ob irgendwas statisch, nicht-statisch, null-terminiert oder nicht-null-terminiert ist.