En C et C++ il est habituel de séparer la déclaration d'une fonction et sa définition dans deux fichier séparés: l'entête contenant la déclaration (fichier .h ou .hh) et le code source proprement dit contenant sa définition (fichier .c ou .cpp). Lorsque l'on veut faire la même chose avec une fonction utilisant un template, on obtient une erreur du type "undefined reference to" lors de la première utilisation de la fonction dans le code.

Un exemple

Par exemple supposons la fonction addition qui retourne la somme de deux nombre de même type:

Tout d'abord le fichier d'entete (addition.hh):

template<typename Type> Type addition(Type a, Type b);

Le code source de la fonction (addition.cc):

template<typename Type> Type addition(Type a, Type b)
{
    return a + b;
}

Une portion de code utilisant cette fonction (main.cc):

#include "addition.hh"
void main()
{
    int a = 3;
    int b = 2;
    int c =0;
    c = addition(a, b)
}

Bien que le code semble correct, la création de lien va échouer avec l'erreur:

/tmp/ccEpROXj.o(.text+0x17c): In function `main':
: undefined reference to `addition(int, int)'

Le pourquoi

Il y a différentes raisons pour lesquels cette erreur apparait. Il s'agit principalement du fait qu'un template n'est pas une fonction mais un modèle utilisé pour générer la fonction. Lorsqu'il est utilisé dans un programme pour générer une fonction, la définition dois être connue et non seulement la déclaration.

Comment s'en sortir

Il existe plusieurs solutions à ce problème.

Insertion de la définition dans le fichier d'entête

La première consiste à inclure la définition dans le fichier d'entête. Pour cela il suffit de fusionner les deux fichiers entête et code source dans un seul fichier ou alors inclure le fichier du code source via une commande include de preprocessing à la fin du fichier d'entête. Cette solution est la plus simple mais le résultat n'est pas forcément très propre. En effet certains compilateur peuvent entrainer une augmentation dramatique de la taille de l'exécutable.

Ajout d'une spécialisation du template

FIXME: A confirmer

On peut également ajouter les déclaration des spécialisations que l'on veut utiliser dans le fichier source de la fonction.

Par exemple en reprenant le fichier source de notre fonction addition, on spécifier les déclarations pour les types int, float et double:

template<typename Type>
Type addition(Type a, Type b)
{
    return a + b;
}

template int addition<int>(int, int);
template float addition<float>(float, float);
template double addition<double>(double, double);

Utilisation du mot clef export

FIXME