2010-08-07 4 views
1

je quelque chose comme ça dans mon code:« symbole externe non résolu » sur la spécialisation de modèle pour tableau de char

template <typename T> 
struct A 
{ 
    void Print(); 
}; 

template <> 
struct A<char*> 
{ 
    void Print() { printf("Char*!\n"); } 
}; 

template <typename T> 
void DoSomething(T& lol) 
{ 
    A<T> a; 
    a.Print(); 
} 

int main() 
{ 
    char a[5]; 
    DoSomething(a); 
} 

Et cela produit l'erreur de liens suivant:

error LNK2019: unresolved external symbol "public: void __thiscall A<char [5]>::Print(void)" ([email protected][email protected][email protected]@QAEXXZ) referenced in function "void __cdecl DoSomething<char [5]>(char const (&)[5])" ([email protected][email protected]@[email protected]) 

Quel type dois-je spécialiser le modèle A pour, afin que je puisse l'utiliser avec un tableau de char? J'ai essayé const char* et d'autres combinaisons de const, char, * et &, et rien ne fonctionne.

Notez que je ne peux pas modifier la fonction DoSomething.

Aussi, si possible, je voudrais que le compilateur déduise automatiquement (ou convertisse) le type de modèle sans le spécifier dans l'appel DoSomething<smth>() dans main().

Répondre

5

a n'a pas le type char*, il a le type char[5], donc le modèle principal est instancié, pas la spécialisation.

Si vous effectuez manuellement la conversion tableau à pointeur, il utilisera la spécialisation:

char a[5]; 
char* aptr = a; 
DoSomething(a); 

Si vous ne voulez pas le modèle primaire à utiliser pour un tableau char, vous pouvez spécialiser modèle:

template <unsigned N> struct A<char[N]> { /* ... */ }; 
+0

Que faire si je ne peux pas (ou ne veux vraiment, vraiment pas) effectuer la conversion de tableau en pointeur? – GhassanPL

+0

@Kronikarz: Ensuite, vous devez spécialiser le modèle pour un type de tableau. –

0
char a[5]; 
char* aPointer = &a[0]; 
DoSomething(aPointer); 

Cela passera un char * à DoSomething.

Voici votre exemple de code complet, modifié pour le faire correctement:

template <typename T> 
struct A 
{ 
    void Print(); 
}; 

template <> 
struct A<char*> 
{ 
    void Print() { printf("Char*!\n"); } 
}; 

template <typename T> 
void DoSomething(T& lol) 
{ 
    A<T> a; 
    a.Print(); 
} 

int main() 
{ 
    char a[5]; 
    char* aPointer = &a[0]; 
    DoSomething(aPointer); 
} 
1

Vous pouvez suivre l'erreur vient de compilation et de se spécialiser pour char[5]. Cependant, il semble que ce soit une spécialisation très étrange à fournir.

Si vous souhaitez spécifier explicitement une spécialisation de DoSomething à utiliser, alors pourquoi ne pas faire exactement cela?

int main() 
{ 
    char a[5]; 
    DoSomething<char *>(a); 
} 

Bien sûr, vous constaterez que cela ne fonctionne toujours pas compilé comme DoSomething prend une référence non-const donc vous avez besoin d'un lvalue de type char *, un ne fera pas temporaire.

int main() 
{ 
    char a[5]; 
    char *p = a; 
    DoSomething<char *>(p); 
} 
0

Une autre possibilité de forcer array-> carie pointeur serait de créer une spécialisation de DoSomething:

template <typename T> 
void DoSomething(const T& lol) 
{ 
    A<T> a; 
    a.Print(); 
} 

template <class T, unsigned N> 
void DoSomething(T(& x)[N]) 
{ 
    DoSomething(x+0); 
} 

(vous devez faire le paramètre de DoSomethingconst puisque référence nonconst ne peut pas fonctionner comme une référence si vous passer des tableaux à cela

+2

Je ne suis pas sûr, mais je pense que fournir une spécialisation explicite de 'DoSomething' pourrait être considéré comme" changer la fonction 'DoSomething'". Changer son paramètre de 'T &' à 'const T &' le fait certainement. –

Questions connexes