2012-01-08 19 views
11

En C++ 03, la deducción del parámetro de plantilla no ocurre en algunos contextos. Por ejemplo:¿Cómo afectan los alias de la plantilla la deducción del parámetro de la plantilla?

template <typename T> struct B {}; 

template <typename T> 
struct A 
{ 
    typedef B<T> type; 
}; 

template <typename T> 
void f(typename A<T>::type); 

int main() 
{ 
    B<int> b; 
    f(b); // ERROR: no match 
} 

Aquí, int no se deduce para T, debido a que un tipo anidado como A<T>::type es un contexto no deducida.

si lo hubiera escrito la función como esta:

template <typename T> struct B {}; 

template <typename T> 
void f(B<T>); 

int main() 
{ 
    B<int> b; 
    f(b); 
} 

todo está bien porque es B<T> un contexto deducido.

En C++ 11, sin embargo, los alias de plantilla se pueden utilizar para ocultar un tipo anidado en una sintaxis similar al segundo ejemplo. Por ejemplo:

template <typename T> struct B {}; 

template <typename T> 
struct A 
{ 
    typedef B<T> type; 
}; 

template <typename T> 
using C = typename A<T>::type; 

template <typename T> 
void f(C<T>); 

int main() 
{ 
    B<int> b; 
    f(b); 
} 

¿Funcionaría la deducción del argumento de la plantilla en este caso? En otras palabras, ¿los alias de plantilla son un contexto deducido o un contexto no deducido? ¿O heredan el estado deducido/no deducido de lo que sea que alias?

+1

Los alias son solo alias. Es como escribir 'template void f (typename A :: type);', que no es deducible. –

+0

posible duplicado de [C++, el argumento de la plantilla no se puede deducir] (http://stackoverflow.com/questions/6060824/c-template-argument-can-not-be-deduced) – Nawaz

+0

Creo que Kerrek SB es correcto sobre esto. Si hubiera proporcionado una cita, no necesitaría salir y buscar uno ;-) –

Respuesta

8

En otras palabras, ¿los alias de la plantilla son un contexto deducido o un contexto no deducido?

Son deducibles como el código equivalente sin usar alias de plantilla. Por ejemplo

template<typename T> 
using ref = T&; 

template<typename T> 
void f(ref<T> r); 

Ahora puede llamar f(x) y T se deduce perfectamente bien. En el momento de definición de f ya, ref<T> se reemplazó por el tipo T&. Y T& es un contexto deducido.

En su caso C<T> se sustituye por typename A<T>::type, y que es un contexto no deducida para T, por lo T no se puede deducir.

+1

La frase clave en la excelente respuesta de Johannes es "En el * tiempo de definición * de' f' ya "(énfasis mío). Es fácil pasar por alto eso, pero saberlo explica todo. –

1

Imagínese esto:

template <typename T> struct Foo { typedef T type; } 
template <> struct Foo<char>  { typedef int type; } 

template <typename T> using mytype = typename Foo<T>::type; 

template <typename T> void f(mytype<T>); 

Ahora si quiero int n; f(n);, ¿cómo podría decidir si quiero o T = intT = char? Todo el problema, que no se ve afectado por los alias de la plantilla, es que no se puede deducir hacia atrás a todas las cosas que podrían definir algo.

1

creo que la cita relevante en la norma el C++ es 14.5.7 [temp.alias] párrafo 2:

Cuando una plantilla-id se refiere a la especialización de una plantilla de alias, que es equivalente a la tipo asociado obtenido por sustitución de sus argumentos de plantilla para los parámetros de plantilla en el id de tipo de la plantilla de alias. [Nota: nunca se deduce un nombre de plantilla de alias. - nota final]

Hay un ejemplo que sigue la cita que efectivamente explica que no tiene sentido utilizar una plantilla de alias en una plantilla de función y con la esperanza de deducir el argumento de la plantilla. Esto aparentemente se aplica incluso para situaciones que no involucran tipos anidados.

+0

Su última declaración es incorrecta. Lo que su cita con respecto a la deducción dice es que no se puede deducir el nombre de la plantilla del alias. Eso es 'template clase C> void f (C ); ref r; f (r); 'no es posible deducir' C == ref' (dada mi definición de 'ref' en mi respuesta). No significa lo que concluyes que significa. –

+0

OK, puedo aceptar esto. Sin embargo, ayer no he encontrado una mejor cotización (pero es posible que haya sido confuddled). ¿Puede indicarme una cita en el estándar? –

+1

lo citó usted mismo. La plantilla-id 'ref ' es equivalente a 'T &' por la cita que ha proporcionado. Y, por lo tanto, la nota no normativa dice que es inutilizable deducir 'ref'. Pero es útil para deducir 'T', debido a este reemplazo temprano. Ver la solución de http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#395 y http://stackoverflow.com/a/6623089/34509 –

Cuestiones relacionadas