2010-12-06 25 views
5

Tengo una clase de rasgo que necesito especializar (y especializar parcialmente) muchas veces.especialización de plantilla parcial ambigua

Algunas especializaciones parciales se solapan:

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; 
}; 

¿Cómo se supone que voy a obtener el mismo resultado con un código de trabajo?

que se volvió loca con enable_if y is_same, ni siquiera estoy seguro de nada que es la manera correcta ...

+2

¿Qué estás ** realmente ** tratando de hacer? –

+2

Debe evitar la superposición. Esa es la respuesta. La pregunta es la pregunta de Karl: ¿Qué estás realmente tratando de hacer? –

+0

Lo siento amigo, pero estás usando C++ incorrecto. Replantea tu solución y/o publica el problema real para obtener una respuesta real. – Squirrelsama

Respuesta

6

Su mejor opción para esto, si no se puede evitar la especialización superposición, es aclarar todas sus se superpone Tendrá que escribir otra especialización para

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

... pero, como todo el mundo dice en los comentarios, lo mejor es evitar la coincidencia, si es posible. Como otros llamaron, el problema puede no coincidir con especializaciones, puede ser que este no sea el mejor enfoque para resolver su problema.

+0

No conozco otras formas de hacer lo que necesito (que escribí en un comentario a la pregunta), y este parece ser el mejor método para lograrlo. – peoro

0

Probar:

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

No estoy seguro de que funcione, el OP probablemente siempre superará los dos parámetros, ya que parece que el objetivo de la clase de rasgos es detectar si los tipos son iguales. –

0

El truco es crear un tipo de ayuda que le dice si algo es un C<Foo> o no:

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; 
}; 

Usted estaba en el camino correcto con enable_if pero is_same parece ser un callejón sin salida:

#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 
}; 

cual se puede probar fácilmente ahora:

#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; 
} 

Usted puede cambiar fácilmente que si usted quiere que su especialización para trabajar sólo con uno de los parámetros a ser un C o lo que quiera.

Cuestiones relacionadas