2011-02-07 21 views
5

Estoy tratando de crear un contenedor de conveniencia C++ alrededor de una antigua API C que utiliza un tipo de datos opaco. Hay una función C particular que toma una cadena de formato, junto con una cantidad variable de argumentos usando las instalaciones C <stdarg.h>. Como parte de mi envoltorio, quiero poder pasar una cantidad arbitraria de argumentos (incluidos objetos C++) a esta función. Sin embargo, dado que obviamente las instalaciones <stdarg.h> no pueden funcionar con datos que no sean POD, creé una función de conversión con plantilla que convierte objetos C++ (como std::string) en equivalentes POD.Desempaquetar la lista de argumentos con la plantilla de variables

Pensé que todo esto sería un ejercicio fácil usando C++ 0x plantillas variadas, pero estoy teniendo dificultades para entender cómo escribir esta función de una manera que desenrolla correctamente el paquete de argumentos al aplicar mi función de conversión a cada argumento

Lo que tengo hasta ahora es:

template <class T, class... Args> 
    void apply(OPAQUE* object, const char* fmt_string, T&& val, Args&&... args) 
    { 
     apply(object, fmt_string, Convert(val), args...); 
    } 

    template <class... Args> 
    void apply(OPAQUE* object, const char* fmt_string, Args&&... args) 
    { 
     C_API_Function_Call(object, fmt_string, args...); 
    } 

Por supuesto, esto no funciona porque la llamada función recursiva en realidad nunca descomprime el Args..., por lo que sólo recursivamente hasta que los desbordamientos de pila. No puedo averiguar cómo hacer que descomprima los argumentos mientras también pasando el argumento actual a la función Convert, y luego pasando recursivamente el resultado.

¿Hay alguna forma de hacerlo?

Respuesta

25

Creo que se necesita la misma sintaxis que cuando lo hace el reenvío perfecto:

template <class... Args> 
void apply(OPAQUE* object, const char* fmt_string, Args&&... args) 
{ 
    C_API_Function_Call(object, fmt_string, Convert(std::forward<Arg>(args))...); 
} 

Los puntos suspensivos ... se puede colocar a la derecha de una expresión que contiene el paquete de discusión, y no sólo directamente en el derecho del paquete de argumento en sí.

Así,:
func (args ...) ampliar a func (arg1, arg2, arg3, [...], argN)
func (args) ... ampliar a func (arg1), func (arg2), [...], func (argN)

+2

No estoy seguro de por qué OP aún no ha cambiado su opinión y aceptó esta respuesta. El actualmente aceptado es obviamente incorrecto, y el tuyo es el correcto. +1 Saludos. –

-1

Por el momento, el borrador C++ 0x no proporciona ninguna solución para eso. Como el problema es similar a la expansión de tuplas, puede leer this discussion y escribir una función de expansión similar.

Cuestiones relacionadas