2009-08-12 16 views
21

I crearon dos funciones simples que obtienen parámetros de plantilla y un struct vacío definir un tipo:¿Por qué la deducción del argumento de la plantilla no funciona aquí?

//S<T>::type results in T& 
template <class T> 
struct S 
{ 
    typedef typename T& type; 
}; 

//Example 1: get one parameter by reference and return it by value 
template <class A> 
A 
temp(typename S<A>::type a1) 
{ 
    return a1; 
} 

//Example 2: get two parameters by reference, perform the sum and return it 
template <class A, class B> 
B 
temp2(typename S<A>::type a1, B a2)//typename struct S<B>::type a2) 
{ 
    return a1 + a2; 
} 

el tipo de argumento se aplica a la struct S para obtener la referencia. Yo los llamo con algunos valores enteros pero el compilador no puede deducir los argumentos:

int main() 
{ 
    char c=6; 
    int d=7; 
    int res = temp(c); 
    int res2 = temp2(d,7); 
} 

de error 1 error C2783: 'Un temperatura (S :: tipo)': no ​​se pudo deducir argumento de plantilla para 'a'

de error 2 error C2783: 'B temp2 (S :: tipo, B)': no ​​podía deduce argumento de plantilla para 'a'


¿Por qué está pasando esto? ¿Es tan difícil de ver que los argumentos de la plantilla son char y int valores?

Respuesta

27

Al igual que la primera nota, el nombre del tipo de letra se utiliza cuando menciona un nombre dependiente. Entonces no lo necesitas aquí.


template <class T> 
struct S 
{ 
    typedef T& type; 
}; 

En cuanto a la creación de instancias de plantilla, el problema es que typename S<A>::type caracteriza un contexto nondeduced para A. Cuando un parámetro de plantilla se utiliza sólo en un contexto nondeduced (en el caso de A en sus funciones) no se toma en consideración para la deducción del argumento de la plantilla. Los detalles se encuentran en la sección 14.8.2.4 del Estándar C++ (2003).

Para que su identificador de llamada, es necesario especificar explícitamente el tipo:


temp<char>(c); 
+2

bienvenido a SO. y +1 :) –

+0

Edité la cita por un tiempo. Primero, entonces +1 :) –

6

Es parece contexto nondeduced. Según C++ estándar 14.8.2.4/4:

Los contextos nondeduced son:

  • El nombre-nested-especificador de un tipo que se especificó usando un calificado-id.
  • un tipo que es un plantilla-id en el que uno o más de los plantilla-argumentos es una expresión que hace referencia a un plantilla-parámetro.

Cuando se especifica un nombre de tipo de una manera que incluye un contexto no deducido, tampoco se graban todos los tipos que comprenden ese nombre de tipo. Sin embargo, un tipo compuesto puede incluir tanto los tipos deducidos como los no deducidos. [Ejemplo: si se especifica un tipo como A<T>::B<T2>, T y T2 no se escriben. Del mismo modo, si se especifica un tipo como A<I+J>::X<T>, I, J y T no se han escrito.Si se especifica un tipo como void f(typename A<T>::B, A<T>), T en A<T>::B no está escrito pero se deduce T en A<T>. ]

+0

¿Puede explicarme esto en palabras simples con ejemplos: 'El especificador de nombre anidado de un tipo que se especificó utilizando un id calificado. Sé que el especificador de nombre anidado es' X :: 'y id calificado es uno que tiene' :: 'como prefijo, pero no puede concluir o comprender todo. Muchas gracias :) –

+0

es como '(** El nombre anidado-especificador de un tipo **) que se especificó utilizando un id calificado. 'o' El especificador de nombre anidado de un (** tipo que se especificó utilizando un id. calificado. **) ' –

4

Deducción trabaja en la dirección de avance:

template <class T> void f(T); 

f(2); // can deduce int from T 

Por qué sucede esto?

No funciona en la dirección hacia atrás (el ejemplo):

template <class A> void g(typename S<A>::type); 

¿Es tan difícil ver que los argumentos de plantilla son carbón e INT valores?

Deducción de la plantilla puede hacer algunas cosas mágicas (Turing-completa), pero no creo que este sea uno de ellos.

Es posible usar algo como (no probado):

template <class SA> void h(SA a1) 
{ 
    STATIC_ASSERT(same_type<SA, S<A>::type>::value); 
    typedef typename SA::type A; 

    ... 
} 

El uso de la biblioteca estática afirman favorito (Boost tiene dos).

+0

Y ahora también en el STL: http://en.cppreference.com/w/cpp/ language/static_assert – ibizaman

Cuestiones relacionadas