2010-02-08 2 views
2

Est-il possible de se spécialiser sur certains (pas tous) paramètres de modèle de classe?Est-il possible de se spécialiser sur certains (pas tous) paramètres de modèle de classe?

Par exemple:

template <typename T, typename U> 
class TC 
{ 
public: 
void Foo(); 
}; 

template <typename T, typename U> 
void TC<T, U>::Foo() 
{ 

} 

template <???, typename U> 
void TC<int, U>::Foo() 
{ 
    //Want this defined for all U but only when T is int. 
} 

int main(int argv, char * args []) 
{ 
TC<int, char> tc; 
return 0; 
} 

Répondre

3

En général, vous pouvez vous spécialiser seulement certains paramètres de modèle d'un modèle de classe, on appelle la « spécialisation partielle ». En faisant cela, vous créez une nouvelle version spécialisée du modèle qui "remplace" la version générale.

Dans votre cas, il semble que vous souhaitiez uniquement spécialiser une partie du modèle, la méthode Foo(), mais ce n'est pas possible. Vous devez spécialiser toute la classe TC:

// specialization for T=int 
template <typename U> 
class TC<int, U> { 
public: 
    void Foo(); 
}; 

// implementation of Foo() for the specialized template 
template <typename U> 
void TC<int, U>::Foo() 
{ 
    //Want this defined for all U but only when T is int. 
} 
0

Si vous souhaitez que de se spécialiser une partie de la classe, vous devez la classe d'origine pour fournir des crochets. Il est généralement décrit comme Traits ou Policies en fonction de la mise en œuvre.

Une classe Traits fait référence à certaines propriétés, et parfois à certaines méthodes, pour un type donné et n'est pas explicitement transmise. Un exemple dans la liste STL est std::iterator_traits<It>.

Une classe Policy est une classe transmise en tant que paramètre de modèle utilisé pour implémenter un certain nombre de fonctionnalités. Un exemple dans la liste STL est std::less<int> dans std::set<int, std::less<int> >.

En général, l'utilisation d'une classe Policy est explicite alors que l'utilisation d'un Traits est implicite ... et donc je préfère le premier au second.

Si votre classe ne pas utiliser ces crochets, puis faire rapport à sth réponse sur la spécialisation partielle et notez que la partielle signifie que certains paramètres sont encore modèle, et non que vous souhaitez que de se spécialiser une partie de la classe, car en effet vous devez tout redéfinir.

1

Pour les cours, oui. Pour les fonctions, non et oui.

La spécialisation de modèle partielle convient aux classes, mais pour les fonctions globales, c'est un peu plus compliqué.

Pour les classes, vous omettez simplement les arguments spécialisés dans la liste des paramètres du modèle et l'inclure dans la définition de classe:

// General template class for a vector 
template <class T, int N> 
struct Vector 
{ 
    T e[N]; 
}; 

// Specialization for N=3 
template <class T> // omit the N 
struct Vector<T, 3> // and include it here 
{ 
    T e[3]; 

    static Vector<T, 3> cross(const Vector<T, 3>& a, const Vector<T, 3>& b) 
    { 
    return Vector<T, 3>(a.e[1] * b.e[2] - a.e[2] * b.e[1], 
         a.e[2] * b.e[0] - a.e[0] * b.e[2], 
         a.e[0] * b.e[1] - a.e[1] * b.e[0]); 

    } 
}; 

Pour les fonctions globales, vous ne pouvez pas faire cela. Vous pouvez soit définir une fonction entièrement générale, soit entièrement spécialisée - la spécialisation partielle des fonctions n'est pas autorisée. Toutefois, vous pouvez partiellement spécialiser une fonction en la créant comme proxy pour une fonction statique d'une classe partiellement spécialisée.

par exemple.

template <class A, class B> 
void foo(A a, B b) 
{ 
    foo_impl::fun(a, b); 
} 

template <class A, class B> 
struct foo_impl 
{ 
    static void fun(A a, B b) 
    { 
    // real implementation here 
    } 
}; 

Vous pouvez ensuite se spécialiser foo_impl de quelque façon que vous voulez, et qui sera reflétée dans foo.

Questions connexes