Manejo de plantillas variadas en c ++ 11
Frecuentes
Visto 4,593 veces
11
Recientemente comencé a usar C++ 11 y leí un tutorial sobre plantillas variádicas. He entendido que podemos definir una plantilla variádica como esta
// example class that uses variadic template
template<typename ...Args> struct mtuple;
Pero, ¿cómo puedo manejar los argumentos de plantilla del mtuple
clase (es decir, cómo sería el get<int>(mtuple_obj)
¿parece?)?
2 Respuestas
4
Lo que get<1>(t)
parece dependerá de la implementación de mtuple
. Una implementación típica hereda recursivamente de un tipo que contiene cada argumento, por lo que mtuple<A,B,C>
hereda de TupleHead<A>
(que tiene un miembro de tipo A
) y también hereda de TupleTail<B,C>
. TupleTail<B,C>
hereda de TupleHead<B>
(que tiene un miembro de tipo B
) y TupleTail<C>
. TupleTail<C>
hereda de TupleHead<C>
(que tiene un miembro de tipo C
.)
Ahora, si le da a cada clase base un parámetro entero también:
mtuple<A,B,C>
hereda de TupleHead<0,A>
y TupleTail<1,B,C>
TupleTail<1,B,C>
hereda de TupleHead<1,B>
y TupleTail<2,C>
TupleTail<2,C>
hereda de TupleHead<2,C>
Ahora es relativamente simple escribir get<1>
, Debido a que el mtuple
tiene una sola clase base única de tipo TupleHead<1,B>
que se puede obtener mediante un upcast, luego devolver el B
miembro de esa clase base.
[Editar: get<1>(m)
necesita saber el tipo B
que corresponde al elemento tupla con índice 1, para eso usas algo como std::tuple_element
que también se basa en la jerarquía de herencia recursiva descrita anteriormente y utiliza la especialización parcial para obtener el TupleHead<1,T>
clase base con índice 1, luego determina el parámetro T
en esa especialización parcial, que da B
en mi ejemplo.]
Muchas de las técnicas que se utilizan con las plantillas variádicas son técnicas de programación funcional, como operar en el primer elemento del paquete de parámetros de la plantilla y luego hacer lo mismo recursivamente en el resto del paquete, hasta que haya procesado todos los elementos. No hay muchas cosas que pueda hacer directamente con un paquete de parámetros de plantilla excepto contar su tamaño (con sizeof...
) o crear una instancia de otra plantilla con ella, por lo que el enfoque habitual es crear una instancia de otra plantilla que separe el paquete Args
dentro ArgHead, ArgsTail...
y procesa la cabeza, luego recursivamente hacer lo mismo para ArgsTail
contestado el 04 de mayo de 12 a las 16:05
4
No existe un mecanismo simple para iterar sobre los valores de una plantilla variádica. Pero esto se puede hacer recursivamente. Aquí hay un ejemplo:
template<typename T, typename... Args>
void print_values(const char *s, T value, Args... args)
{
while (*s) {
if (*s == '%' && *(++s) != '%') {
std::cout << value;
++s;
print_values(s, args...);
return;
}
cout << *(s++);
}
}
Entonces, si llamo print_values("%d %d %d", 1, 2, 3)
Obtengo este árbol de recursión:
print_values("%d %d %d", 1, 2, 3) // value -> 1, args... -> 2,3
print_values("%d %d", 2, 3) // value -> 2, args... -> 3
print_values("%d", 3) // value -> 3, args... -> NULL
print_values("") // value -> NULL, args... -> NULL
llamo recursivamente print_values()
incluso cuando *s == 0 para detectar argumentos adicionales
contestado el 04 de mayo de 12 a las 12:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ c++11 variadic-templates or haz tu propia pregunta.
La magia de plantillas Variadic es realmente mágica, tienes que experimentar con ella, así como mirar muchos ejemplos de código diferentes para ver qué y por qué está pasando allí. Aquí está mi intento de escribir mi propia clase Tuple (aunque no mires
Tie()
;RE), como uno de esos ejemplos de código, también hay muchos aquí, en SO: explore plantillas-variadas y tratar de entenderlos. - Griwesun par de preguntas relacionadas interesantes: stackoverflow.com/a/7868427/170521 y stackoverflow.com/q/7870498/170521 - lurscher