PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++] Template-Funktion wird beim Linken nicht gefunden


Gast
2009-12-09, 11:12:27
Hi,
ich habe mir ne Template-Funktion geschrieben und Deklaration und Definition in Header und CPP aufgeteilt. Leider findet er nun die Funktion beim Linken nicht.
Hier mal ein Minimalbeispiel:

Helpers.h

#ifndef HELPERS_H_
#define HELPERS_H_

#include <string>

namespace Helpers
{
template<typename T> std::string ValueToString(T value);
};
#endinf


Helpers.cpp

#include "helpers.h"

template<typename T> std::string Helpers::ValueToString(T value)
{
std::stringstream out;
out << value;
return out.str();
}


main.cpp

#include "helpers.h"

int main()
{
std::string test = Helpers::ValueToString<int>(5);
}


Fall jemand noch die Fehlermeldung von VS 2008 haben will:

error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Helpers::ValueToString<int>(int)" (??$ValueToString@H@Helpers@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$alloc ator@D@2@@std@@H@Z) referenced in function _main main.obj

del_4901
2009-12-09, 11:25:04
Die Trennung in Header und Source geht mit Templates nicht, du kannst es mal mit dem keyword extern probiern, aber das duerfte VS noch nicht unterstuetzen wenn das ueberhaupt Jemand unterstuetzt.

Gast
2009-12-09, 11:43:54
Ahh danke für die Info - bin schon fast verrückt geworden. Nach deinem Tipp habe ich auch prompt was dazu im Netz gefunden, dass das noch ausführlicher erklärt. Vielleicht hier dieser Text (http://www.c-plusplus.de/forum/viewtopic-var-t-is-128361-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html) (Siehe Abschnitt 7) ja jemandem.

The_Invisible
2009-12-09, 12:35:04
das selbe übrigens mit inline methoden (gcc4)

mfg

Gnafoo
2009-12-09, 14:38:54
Das Problem ist im Wesentlichen, dass der C++-Compiler jede cpp-Datei für sich getrennt als Übersetzungseinheit verarbeitet. Bei normalen Klassen ist das kein Problem, denn die Deklaration in der Header-Datei enthält alle Informationen, die der Compiler benötigt, um mit der Klasse zu arbeiten, Funktionen aufzurufen etc.

D. h. wenn du die Klasse verwendest werden einfach nur Funktionsaufrufe erzeugt, die erst dann erfüllt werden können, wenn die cpp-Datei zur Klasse selbst auch verarbeitet wurde. Dann gibt es passende Methoden, so dass der Linker mit beiden Übersetzungseinheiten ein fertiges Programm erzeugen kann.

Bei Templates ändert sich das grundlegend, denn hinter einem Template kann eine Vielzahl verschiedener Funktionen/Klassen stecken. Wenn man also das Template als getrennte Übersetzungseinheit verarbeiten wollte, dann müsste man zu diesem Zeitpunkt bereits wissen, für welche Template-Parameter man Code erzeugen muss (z. B. eine Liste von ints, eine Liste von longs etc.).

Das kann aber gar nicht funktionieren, denn spätestens wenn man Templates in Bibliotheken verwenden will gibt es Code der dein Template aufruft, aber zur Compile-Zeit unbekannt ist. Also muss das Template in die Header-Datei, denn wenn es sich dort befindet, wird es über #include in alle anderen Übersetzungseinheiten, die es verwenden eingebunden und dann kann dort der jeweils notwendige Code erzeugt werden.

Coda
2009-12-09, 17:39:47
Die Trennung in Header und Source geht mit Templates nicht, du kannst es mal mit dem keyword extern probiern, aber das duerfte VS noch nicht unterstuetzen wenn das ueberhaupt Jemand unterstuetzt.
Nur Comeau C++, sonst keiner. Selbst Compiler die Comeau als Frontend verwenden (Intel) haben es - aus gutem Grund - deaktiviert.