2010-12-06 38 views
5

J'ai une classe de caractères que j'ai besoin de spécialiser (et de spécialiser partiellement) plusieurs fois.Spécialisation de modèle partiel ambigu

Certaines spécialisations partielles se chevauchent:

template< typename T > struct C { }; 
template< typename T1, typename T2 > struct TRAIT { }; 

template< typename T > struct TRAIT< T, T > { }; 
template< typename T1, typename T2 > struct TRAIT< C<T1>, C<T2> > { }; 

int main() { 
    // ERROR! could be both TRAIT<T,T> [with T = C<int>] 
    //     and TRAIT<T1,T2> [with T1 = T2 = int] 
    TRAIT< C<int>, C<int> > foo; 
    return 0; 
}; 

Comment suis-je censé obtenir le même résultat avec un code de travail?

Je suis allé fou avec enable_if et is_same, je ne suis même pas sûr que plus il est la bonne façon ...

+2

Qu'essayez-vous vraiment de faire **? –

+2

Vous devez éviter les chevauchements. C'est la réponse. La question est celle posée par Karl: Qu'est-ce que vous essayez vraiment de faire? –

+0

Je suis désolé mate, mais vous utilisez faux C++. Repensez votre solution et/ou postez le problème réel pour obtenir une réponse réelle. – Squirrelsama

Répondre

6

Votre meilleur pari pour cela, si vous ne pouvez pas éviter la spécialisation qui se chevauchent, est de clarifier tous vos chevauchements. Vous aurez besoin d'écrire une autre spécialisation pour

template< typename T> struct TRAIT< C<T>, C<T> > { }; 

... mais, comme tout le monde l'a déjà dit dans les commentaires, il est préférable d'éviter tout chevauchement si possible. Comme d'autres l'ont appelé, le problème n'est peut-être pas le chevauchement des spécialisations, il se peut que ce ne soit pas la meilleure approche pour résoudre votre problème.

+0

Je ne connais pas d'autres façons de faire ce dont j'ai besoin (que j'ai écrit dans un commentaire à la question), et cela semble être la meilleure méthode pour y parvenir – peoro

0

Essayez:

template< typename T > struct C { }; 
template< typename T1, typename T2 = T1> struct TRAIT { }; 
           // ^^^^^^^^^ 
           // Default Type is T1 

int main() 
{ 
     TRAIT<C<int> >   foo1; 
     TRAIT<C<int>, C<int> > foo2; 

     foo1 = foo2; 
     return 0; 
}; 
+0

Je ne suis pas sûr que cela fonctionnerait, l'OP passera probablement toujours les deux paramètres, car il semble que le but de la classe de traits à détecter si les types sont égaux. –

0

L'astuce consiste à créer un type d'aide qui vous indique si quelque chose est un C<Foo> ou non:

template <typename T> struct C {}; 

template <typename T> struct is_C { 
    static bool const value = false; 
}; 
template <typename T> struct is_C<C<T>> { 
    static bool const value = true; 
}; 

Vous étiez sur la bonne voie avec enable_if mais is_same semble être une impasse:

#include <type_traits> 

template <typename T1, typename T2, typename Enabled = void> struct Trait { 
    static char const test = 'D'; // default 
}; 

template <typename T> struct Trait< 
    T, 
    T, 
    typename std::enable_if<!is_C<T>::value >::type 
> { 
    static char const test = 'N'; // non-C 
}; 

template <typename T1, typename T2> struct Trait< 
    T1, 
    T2, 
    typename std::enable_if< is_C<T1>::value && is_C<T2>::value >::type 
> { 
    static char const test = 'C'; // some C 
}; 

vous pouvez tester facilement maintenant:

#include <iostream> 

int main() { 
    Trait< C<int>, C<float> > foo1a; 
    Trait< C<int>, C<int> > foo1b; 
    Trait< int, int > foo2; 
    Trait< int, float > foo3; 
    std::cout << "Trait<C<int>,C<float>> : " << foo1a.test << std::endl; // prints 'C' 
    std::cout << "Trait<C<int>,C<int>> : " << foo1b.test << std::endl; // prints 'C' 
    std::cout << "Trait<int,int> : " << foo2.test << std::endl; // prints 'N' 
    std::cout << "Trait<int,float> : " << foo3.test << std::endl; // prints 'D' 
    return 0; 
} 

Vous pouvez facilement changer que si vous voulez que votre spécialisation pour travailler uniquement avec l'un des paramètres à un C ou tout ce que vous aimez.