template - typedef c++
¿Por qué la deducción del argumento de la plantilla no funciona aquí? (3)
Creé dos funciones simples que obtienen los parámetros de la plantilla y una estructura vacía que define un tipo:
//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 estructura S para obtener la referencia. 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);
}
Error 1 error C2783: ''A temp (S :: type)'': no se pudo deducir argumento de plantilla para ''A''
Error 2 error C2783: ''B temp2 (S :: tipo, B)'': no se pudo deducir el argumento de la plantilla para ''A''
¿Por qué está pasando esto? ¿Es tan difícil de ver que los argumentos de la plantilla sean valores char e int ?
Al igual que la primera nota, el nombre del tipo de letra se usa cuando mencionas un nombre dependiente . Entonces no lo necesitas aquí.
template <class T>
struct S
{
typedef T& type;
};
Con respecto a la typename S<A>::type
instancias de plantilla, el problema es que typename S<A>::type
caracteriza un contexto no deducido para A. Cuando un parámetro de plantilla se usa solo en un contexto no deducido (el caso de A en sus funciones) no se toma en consideración para 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 hacer que su llamada funcione, debe especificar explícitamente el tipo:
temp<char>(c);
La deducción funciona en la dirección de avance:
template <class T> void f(T);
f(2); // can deduce int from T
¿Por qué está pasando esto?
No funciona en la dirección hacia atrás (su ejemplo):
template <class A> void g(typename S<A>::type);
¿Es tan difícil de ver que los argumentos de la plantilla sean valores char e int?
La deducción de la plantilla puede hacer algunas cosas mágicas (Turing completas), pero no creo que esta sea una de ellas.
Puede 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;
...
}
Usando su biblioteca de afirmación estática favorita (Boost tiene dos).
Se ve como un contexto no deducido. De acuerdo con el estándar C ++ 14.8.2.4/4:
Los contextos no dictados son:
- El especificador de nombre anidado de un tipo que se especificó utilizando un id calificado .
- Un tipo que es un id de plantilla en el que uno o más de los argumentos de plantilla es una expresión que hace referencia a un parámetro de plantilla .
Cuando se especifica un nombre de tipo de una manera que incluye un contexto no deducido, todos los tipos que comprenden ese nombre de tipo tampoco se escriben. Sin embargo, un tipo compuesto puede incluir tanto los tipos deducidos como los no deducidos. [ Ejemplo : si un tipo se especifica como
A<T>::B<T2>
, tantoT
comoT2
no se escriben. Del mismo modo, si un tipo se especifica comoA<I+J>::X<T>
,I
,J
yT
no se escriben. Si un tipo se especifica comovoid f(typename A<T>::B, A<T>)
, elT
enA<T>::B
no se escribe pero se deduceT
enA<T>
. ]