2008-10-02 5 views
26

Le code suivant:"utilisation invalide de type incomplet" erreur avec une spécialisation de modèle partiel

template <typename S, typename T> 
struct foo { 
    void bar(); 
}; 

template <typename T> 
void foo <int, T>::bar() { 
} 

me donne l'erreur

invalid use of incomplete type 'struct foo<int, T>' 
declaration of 'struct foo<int, T>' 

(. J'utilise gcc) Ma syntaxe partielle spécialisation erronée? Notez que si je supprime le deuxième argument:

template <typename S> 
struct foo { 
    void bar(); 
}; 

template <> 
void foo <int>::bar() { 
} 

puis il compile correctement.

Répondre

32

Vous ne pouvez pas spécialiser partiellement une fonction. Si vous souhaitez le faire sur une fonction membre, vous devez partiellement spécialiser l'ensemble du modèle (oui, c'est irritant). Sur une grande classe modélisée, pour spécialiser partiellement une fonction, vous auriez besoin d'une solution de contournement. Une structure de membre modèle (par exemple template <typename U = T> struct Nested) fonctionnerait peut-être. Ou vous pouvez essayer de dériver d'un autre modèle qui se spécialise partiellement (fonctionne si vous utilisez la notation this->member, sinon vous rencontrerez des erreurs de compilation).

3

Si vous avez besoin de se spécialiser en partie un constructeur, vous pouvez essayer quelque chose comme:

template <class T, int N> 
struct thingBase 
{ 
    //Data members and other stuff. 
}; 

template <class T, int N> struct thing : thingBase<T, N> {}; 

template <class T> struct thing<T, 42> : thingBase<T, 42> 
{ 
    thing(T * param1, wchar_t * param2) 
    { 
     //Special construction if N equals 42. 
    } 
}; 

Note: cela a été anonymisées de quelque chose que je travaille. Vous pouvez également utiliser ceci quand vous avez une classe de modèle avec beaucoup, beaucoup de membres et vous voulez juste ajouter une fonction.

5

Bien que coppro ait déjà mentionné deux solutions et qu'Anonymous m'ait expliqué la seconde, il m'a fallu un certain temps pour comprendre le premier. Peut-être que le code suivant est utile pour quelqu'un qui trébuche sur ce site, qui se classe toujours haut dans google, comme moi. L'exemple (passer un vecteur/tableau/élément unique de numericT comme dataT et y accéder via [] ou directement) est bien sûr quelque peu artificiel, mais devrait illustrer comment vous pouvez vraiment vous rapprocher de la spécialisation partielle d'une fonction membre en l'enveloppant dans une classe partiellement spécialisée.

/* The following circumvents the impossible partial specialization of 
a member function 
actualClass<dataT,numericalT,1>::access 
as well as the non-nonsensical full specialisation of the possibly 
very big actualClass. */ 

//helper: 
template <typename dataT, typename numericalT, unsigned int dataDim> 
class specialised{ 
public: 
    numericalT& access(dataT& x, const unsigned int index){return x[index];} 
}; 

//partial specialisation: 
template <typename dataT, typename numericalT> 
class specialised<dataT,numericalT,1>{ 
public: 
    numericalT& access(dataT& x, const unsigned int index){return x;} 
}; 

//your actual class: 
template <typename dataT, typename numericalT, unsigned int dataDim> 
class actualClass{ 
private: 
    dataT x; 
    specialised<dataT,numericalT,dataDim> accessor; 
public: 
    //... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ... 
}; 
Questions connexes