Was passiert nun, wenn man sein Programm auf mehrere Quelltexte verteilt?
In einem Modul steht die Definition der Templatefunktion, hier kann der
Compiler beim Übersetzen alle nötigen Versionen erzeugen; er weiß aber nicht,
welche benötigt werden. In den anderen Quelltexten steht nur eine Deklaration;
der Compiler weiß hier, welche Versionen kompiliert werden müssen, sieht
aber die dazu nötige Definition nicht und behandelt die benötigte
Funktion deshalb als extern
. Aus diesem Grund muß man in dem Modul mit
der Definition alle benötigten Versionen explizit deklarieren (zum Beispiel im obigen
Beispiel als int min( int, int );
usw.).
Dann sieht der Compiler, was der
Programmierer braucht und kann entsprechende Versionen in diesem Modul
erzeugen. Dagegen ist es nicht immer empfehlenswert, die Definition über eine
Headerdatei allen Modulen direkt zur Verfügung zu stellen: dann würden von
ein und derselben Funktion eventuell mehrere Exemplare erstellt und
zusammengebunden. Dies ist theoretisch nicht zulässig; auf manchen Systemen
aber möglich. So wird das Programm nicht mehr portabel sein und außerdem
unnötig groß.
Wie man es dreht und wendet, eine optimale Strategie für alle Fälle gibt es nicht. Man hat hier letztlich folgende Lösungsmöglichkeiten:
Je nach System kann das zu langen Übersetzungszeiten und/oder großen Programmen führen. Daher ist diese Möglichkeit nicht generell empfehlenswert.
Zudem kann man sich (ebenso wie bei der ersten Möglichkeit) Probleme
einhandeln durch Definitionen vor dem jeweiligen #include
, was
zu unterschiedlichen Definitionen der Funktion in den verschiedenen Modulen
führen kann.
template<class T> T min( const T &a, const T &b )
{
return a<b ? a : b
}
int min( int, int );
double min( double, double );
char min( char, char );
In allen anderen Modulen reichen dann die Deklarationen.
Diese Vorgehensweise funktioniert gut, setzt aber voraus daß man beim Schreiben desjenigen Moduls, in dem die Definition der template-Funktion enthalten ist, bereits alle zu erzeugenden Versionen kennt. Dies ist leider nicht immer der Fall.
Man definiert die template-Funktion in genau einem Modul, und setzt
ein export davor:
export template<class T> T min( const T &a, const T &b )
{
return a<b ? a : b
}
In den anderen Modulen wird nur noch die Deklaration (beispielsweise über eine Headerdatei) bekannt gemacht (ohne export).
Der Compiler muß nun zusehen, wie er damit klar kommt. Das kann mehr Zeit beim Übersetzen kosten, aber es funktioniert in jedem Fall.
AnyWare@Wachtler.de