Ricardo
Tengo dos funciones variádicas como foo(format, ...)
y bar(format, ...)
. Quiero implementar la función foo
para que pueda invocar bar
con la misma lista de argumentos que tiene. Eso es,
foo(format...)
{
...
bar(format, ...);
}
Por ejemplo, invocando foo("(ii)", 1, 2)
invocará bar
con los mismos argumentos bar("(ii)", 1, 2)
. ¿Cómo debería esto foo
¿Se implementará la función?
PD: función bar
es de una biblioteca heredada que no puedo cambiar su interfaz.
AnT apoya a Rusia
No se puede hacer, siempre y cuando todo lo que tenga sea un montón si funciona con ...
argumentos
Tienes que planificar con anticipación cosas como esa e implementar cada función variable en dos etapas.
void vfoo(format, va_list *args) {
/* Process `*args` */
}
void foo(format, ...) {
va_list args;
va_start(args, format);
vfoo(format, &args);
va_end(args);
}
Una vez que haya implementado cada una de sus funciones variádicas a través de un par de va_list *
función y ...
función, puede delegar las llamadas usando el va_list *
versiones de las funciones
void vfoo(format, va_list *args) {
...
vbar(format, args);
...
}
CCG puede construir llamadas a funciones en tiempo de ejecución.
foo() {
void *args = __builtin_apply_args();
void *ret = __builtin_apply(bar, args, ???);
__builtin_return(ret);
}
???
es la cantidad de espacio de pila que ocupan los argumentos, lo que no es necesariamente trivial de calcular: deberá comprender cuáles son los argumentos y los detalles específicos de la arquitectura sobre cómo se pasan.
Otras extensiones de GCC permiten más trucos con macros y funciones en línea.
Respuesta corta: no puedes. Haz que la barra tome un va_list
. Si está dispuesto a bloquear esto en un compilador específico, probablemente podría hacerlo con el ensamblado en línea, pero con C o C++ estándar no es posible.
Como regla general, siempre debe implementar sus funciones vararg en términos de va_list
y luego hacer una función de puntos suspensivos de envoltura llamando al real va_list
función.
-
No estoy de acuerdo con la ‘respuesta corta’. Se puede hacer en C++ 0x con plantillas variadas (ver respuesta en otro lugar). Sin embargo, solo voy a las etiquetas de preguntas, la de C ++ en particular 🙂
– phooji
21 de marzo de 2011 a las 21:08
-
@Max Lybbert: ¿Cuál de esos sería C++ 0x?
– phooji
21 de marzo de 2011 a las 21:19
-
@phooji: c ++ 0x no es c ++ (todavía), no responderá a una Q etiquetada con c ++ con c ++ 0x 🙂
– Erik
21 de marzo de 2011 a las 21:20
-
@Erik: Lo sé… pero ¿realmente quiere que el comité también dedique tiempo al nombre? :-pag
– phooji
21 de marzo de 2011 a las 21:32
-
@Max Lybbert: Ah. Estaba leyendo demasiado en tu comentario. Disculpas.
– phooji
21 de marzo de 2011 a las 23:24
phooji
Esto funciona en C++:
#include <iostream>
template<typename Format>
void meheer(const Format& format) {
std::cout << format << std::endl;;
}
template<typename Format, typename Elt, typename ... Args>
void meheer(const Format& format, const Elt & e, const Args&... args) {
std::cout << format << e;
meheer(format, args...);
}
template<typename Format, typename ... Args>
void ohai(const Format& format, const Args&... args) {
meheer(format, args...);
}
int main(int argc, char ** argv) {
ohai(1,2,3);
return EXIT_SUCCESS;
}
Producción:
12131
Por supuesto, esto es específico de C++0x, pero funciona en mi versión no muy reciente de gcc. Ver también: http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic_templates
Actualizar Se agregó un ejemplo completo.
Duplicado de stackoverflow.com/questions/150543/…
– Adam Rosenfield
21 de marzo de 2011 a las 21:32
No sé lo que está tratando de lograr, pero estoy casi dispuesto a apostar que encontrará útiles las siguientes funciones de biblioteca estándar:
vprintf()
,vfprintf()
yvsprintf()
.– Émile Cormier
21 de marzo de 2011 a las 21:34
¿Responde esto a tu pregunta? Reenviar una invocación de una función variádica en C
– imz — Iván Zakharyaschev
5 abr a las 16:46