123 votes

définition multiple de la spécialisation de modèles lors de l'utilisation d'objets différents

Lorsque j'utilise spécialisée modèle dans les différents fichiers objets, je reçois une "définition de plusieurs" erreur lors de la liaison. La seule solution que j'ai trouvé consiste à utiliser le "inline" de la fonction, mais il semble juste comme certains solution de contournement. Comment puis-je résoudre ce problème sans utiliser le mot clé "inline"? Si ce n'est pas possible, pourquoi?

Voici l'exemple de code:

paulo@aeris:~/teste/cpp/redef$ cat hello.h 
#ifndef TEMPLATE_H
#define TEMPLATE_H

#include <iostream>

template <class T>
class Hello
{
    public:
 void print_hello(T var);
};

template <class T>
void Hello<T>::print_hello(T var)
{
    std::cout << "Hello generic function " << var << "\n";
}

template <> //inline
void Hello<int>::print_hello(int var)
{
    std::cout << "Hello specialized function " << var << "\n";
}

#endif

paulo@aeris:~/teste/cpp/redef$ cat other.h 
#include <iostream>

void other_func();

paulo@aeris:~/teste/cpp/redef$ cat other.c 
#include "other.h"

#include "hello.h"

void other_func()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);
}

paulo@aeris:~/teste/cpp/redef$ cat main.c 
#include "hello.h"

#include "other.h"

int main()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);

    other_func();

    return 0;
}

paulo@aeris:~/teste/cpp/redef$ cat Makefile
all:

g++ -c autres.c -o d'autres.o-Wall -Wextra g++ main.c autres.o -o -Wall-Wextra


Enfin:

paulo@aeris:~/teste/cpp/redef$ make
g++ -c other.c -o other.o -Wall -Wextra
g++ main.c other.o -o main -Wall -Wextra
other.o: In function `Hello<int>::print_hello(int)':
other.c:(.text+0x0): multiple definition of `Hello<int>::print_hello(int)'
/tmp/cc0dZS9l.o:main.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: ** [all] Erro 1

Si je décommentez la "inline" à l'intérieur de bonjour.h le code de compiler et de l'exécuter, mais il semble tout simplement une sorte de "solution de contournement" pour moi: que faire si la fonction spécialisée qui est gros et utilisé de nombreuses fois? Vais-je obtenir un gros binaire? Est-il un autre moyen pour ce faire? Si oui, comment? Si non, pourquoi?

J'ai essayé de chercher des réponses, mais je n'ai eu "use inline", sans autre explication.

Merci

162voto

Stuart Golodetz Points 12679

Intuitivement, lorsque vous pleinement se spécialisent quelque chose, il ne dépend pas d'un paramètre de modèle plus-donc, sauf si vous faites de la spécialisation en ligne, vous avez besoin de le mettre dans un .fichier cpp au lieu d'un .h ou vous vous retrouvez violation de l'une définition de la règle comme David le dit. Notez que lorsque vous avez en partie se spécialisent modèles, les spécialisations partielles ne dépendent toujours de l'un ou plusieurs des paramètres de modèle, de sorte qu'ils continuent d'aller dans une .h fichier.

62voto

Le mot-clé inline est plus de dire au compilateur que le symbole est présent dans plus d'un fichier objet, sans violer l'Une Définition de la Règle que le sujet réel de l'in-lining, le compilateur peut décider de faire ou ne pas faire.

Le problème que vous rencontrez est que sans la ligne, la fonction sera compilé dans toutes les unités de traduction qui incluent l'en-tête, en violation de l'ODR. L'ajout d' inline il est la bonne façon de faire. Sinon, vous pouvez déclarer avant la spécialisation et de la fournir dans une seule unité de traduction, comme vous le feriez avec toute autre fonction.

26voto

Crazy Eddie Points 23778

Vous avez explicitement instancier un modèle dans votre en-tête (void Hello<T>::print_hello(T var)). Cela permettra de créer de multiples définitions. Vous pouvez résoudre de deux manières:

1) Faites votre instanciation en ligne.

2) Déclarer l'instanciation dans un en-tête et puis le mettre en œuvre dans un cpp.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X