2011-08-08 31 views
10

Puede alguien explicar por qué son esas dos especialidades indistinguibles al compilador (gcc 4.5.1 @ Ideone)Plantilla especialización parcial

http://ideone.com/9tNux

template <typename... T> struct S; 

template<typename A, typename B, typename... C> 
struct S<A, B, C...> { 
    int f() {return 1;} 
}; 

template<typename... A, typename... C> 
struct S< S<A...>, C...> { 
    int f() {return 2;} 
}; 

y cuando intento crear una instancia de S<S<a, b>, a, b> o2; compilador se queja:

prog.cpp:20:21: error: ambiguous class template instantiation for 'struct S<S<a, b>, a, b>' 
prog.cpp:6:22: error: candidates are: struct S<A, B, C ...> 
prog.cpp:11:33: error:     struct S<S<A ...>, C ...> 
prog.cpp:20:21: error: aggregate 'S<S<a, b>, a, b> o2' has incomplete type and cannot be defined 

Y cuando la última especialización se cambia a:

template<typename... A, typename B, typename... C> 
struct S< S<A...>, B, C...> { 
    int f() {return 2;} 
} 

todo funciona bien.

+0

Creo que también podría agregar el código en esta publicación, ya que es muy importante para la pregunta. – UncleBens

+0

Código @UncleBens agregado. – Predrag

Respuesta

9

Mi comprensión de la cuestión:

typedef S<S<a, b>, c, d> S2; 

Aquí S<a,b> coincide con la segunda especialización mejor. Sin embargo, c, d es una mejor coincidencia para los argumentos restantes de la primera especialización (lista única arg + lista frente a). Por lo tanto, es 1: 1.

Si comenta en B en la segunda especialización, entonces la segunda especialización coincide mejor porque es más especializada para el primer argumento (S<...>) y el resto son igualmente buenos.

+0

¡Buena explicación, +1! Mucho mejor que el desastre que hice. –

+0

Fácil de entender. ¡Gracias! – Predrag

8

Hice un lío de esto; debería estar bien ahora, pero el crédito se debe a @UncleBens a continuación, quien lo hizo bien (y debería obtener el "aceptar").


Sin la B en su tercera versión, que tienen dos especializaciones parciales que son igualmente específico cuando se instancia S<S<X,Y,Z>, T1, T2, T3>:

  • Primera PS: A = S<X,Y,Z>, B = T1, C... = T2, T3.
  • Segunda PS sin B: A... = X,Y,Z, C... = T1, T2, T3.
  • Segunda PS con B: A... = X,Y,Z, B = T1, C... = T2, T3.

¡Esto no establece elementos comparables en el orden de especialización parcial!

Tenga en cuenta que puede decir template <typename ...> struct S; y template <typename A, typename ...B> struct S<A, B...>; y el segundo es más específico que el primero porque tiene más parámetros no variados.

Pero, por otra parte, sin el B, cuando se dice S<S<X,Y,Z>,T1,T2,T3>, entonces el primer argumento coincide mejor en la segunda PS, pero el resto de argumentos que coincida mejor en el primer PS. Sin embargo, con el B en su lugar, el segundo PS es más específico.

comparar esto con la especialización parcial que es en realidad más específica:

template <typename ...A, typename B, typename ...C> 
struct S<B, std::tuple<C...>, std::tuple<C...>> { /* ... */ }; 

Ahora está claro cómo si una instancia dada coincide con la especialización o sólo la forma general. La especialización tiene un número fijo de parámetros (3), por lo que gana otra especialización con un número variable de argumentos.

+0

Pero mis especializaciones no son ', B, C ...>' y ', C ...>'. Son '' y '< S, C ...>'. – Predrag

+0

Esta respuesta parece incorrecta, porque en su ejemplo de apertura la segunda especialización parece más especializada que la primera. Parece que la regla es que 'A' triunfa sobre' A ... ': en la pregunta de OP, la segunda especialización coincide mejor con el primer argumento, pero la primera especialización concuerda mejor con el segundo argumento. De ahí que compile si B está comentado. – UncleBens

+0

@UncleBens: Sí, lo noté ... un segundo, déjeme editarlo –

Cuestiones relacionadas