c++ - Especialización parcial de plantillas variadic
c++11 templates (1)
14.8.2.4, sección 11 (me refiero al borrador N3242).
En la mayoría de los casos, todos los parámetros de plantilla deben tener valores para que la deducción tenga éxito, pero para fines de ordenación parciales, un parámetro de plantilla puede permanecer sin un valor siempre que no se use en los tipos que se utilizan para ordenamiento parcial. [Nota: un parámetro de plantilla usado en un contexto no deducido se considera usado. -finalizar] [Ejemplo:
template <class T> T f(int); // #1 template <class T, class U> T f(U); // #2 void g() { f<int>(1); // calls #1 }
En tu caso, se usará el # 3.
Considere la siguiente plantilla de clase ''X'' y sus especializaciones parciales.
template <class ...Types>
struct X {}; // #1
template <class T1>
struct X<T1> {}; // #2
template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3
X<int> x; // #2 or #3 ?
Sospecho que X <int> es ambiguo. Es porque:
Es obvio que tanto el n. ° 2 como el n. ° 3 son más especializados que n. ° 1, n. ° 2 y n. ° 3 comparados ahora. De acuerdo con 14.5.5.2, consideremos cuál de los siguientes # 2 ''y # 3'' es más especializado.
template <class T1>
void f(X<T1>); // #2''
template <class T1, class ...Types>
void f(X<T1, Types...>); // #3''
De acuerdo con 14.8.2.4, el primer paso es la deducción del argumento de la plantilla usando # 2 ''como la plantilla del argumento y # 3'' como la plantilla del parámetro. Dado el único tipo de argumento es X <A1>, el T1 deducido es A1, y Types está vacío.
A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {}
El segundo paso se realiza usando # 3 ''como la plantilla de argumento y # 2'' como la plantilla de parámetro. Dado el único tipo de argumento es X <A1, Args ...>, de acuerdo con 14.8.2.5/9 (nótese que este párrafo ha sido revisado recientemente por N3281), Args simplemente se ignora, el T1 deducido es A1 y la deducción del argumento tiene éxito.
A = X<A1, Args...>, P = X<T1> => T1 = A1 (Args is ignored)
Finalmente, las deducciones del argumento bidireccional tuvieron éxito. Entonces el # 2 es tan especializado como el # 3. En conclusión, X <int> es ambiguo.
Mi pregunta es: "¿es correcta mi interpretación?"
Si esta interpretación es correcta, la definición de ''std :: common_type'' en 20.9.7.6/3 es inapropiada.
template <class ...T>
struct common_type; // #1
template <class T>
struct common_type<T> // #2
{
typedef T type;
};
template <class T, class U>
struct common_type<T, U> // #3
{
typedef
decltype(true ? declval<T>() : declval<U>())
type;
};
template <class T, class U, class ...V>
struct common_type<T, U, V...> // #4
{
typedef typename
common_type<typename common_type<T, U>::type, V...>::type
type;
};
Cuando se usa common_type <A, B>, # 3 y # 4 son ambiguos.
Nota: en el primer ejemplo, GCC 4.7.0 (instantánea) y Clang 3.0 seleccionan # 2. Sin embargo, estos compiladores son tan poco confiables que no siguen los otros cambios de N3281.