2012-01-16 18 views
11

¿Hay una mejor manera de "sobrecargar" una macro como esta? Necesito una macro que acepte varios números de parámetros.Sobrecarga C macros

#define DEBUG_TRACE_1(p1) std::string p[] = {p1}; log _log(__FUNCTION__, p, 1) 
#define DEBUG_TRACE_2(p1, p2) std::string p[] = {p1, p2}; log _log(__FUNCTION__, p, 2) 
#define DEBUG_TRACE_3(p1, p2, p3) std::string p[] = {p1, p2, p3}; log _log(__FUNCTION__, p, 3) 
#define DEBUG_TRACE_4(p1, p2, p3, p4) std::string p[] = {p1, p2, p3, p4}; log _log(__FUNCTION__, p, 4) 
#define DEBUG_TRACE_5(p1, p2, p3, p4, p5) std::string p[] = {p1, p2, p3, p4, p5}; log _log(__FUNCTION__, p, 5) 

llamado así

DEBUG_TRACE_2("more", "params"); 
+1

Hay compatibilidad con algunos varargs en el procesador de macros C++ (no sé nada de ANSI C), pero todo el tiempo Intento usarlo. Parece arriesgarse a causar una implosión del universo conocido. –

+1

Un poco aquí: http: //stackoverflow.com/questions/679979/how-to-make-a-variadic-macro-variable-number-of-arguments –

+1

'#define DEBUG_TRACE (ar, n) std :: cadena p [] = ar; log _log (__ FUNCTION __, p, n) ', llamada con' DEBUG_TRACE ({"more", "params"}, 2); 'era demasiado simple? –

Respuesta

19

La manera más fácil de hacer que su ejemplo específico sería con una macro variadic:

#define DEBUG_TRACE(...)          \ 
    do {              \ 
     std::string p[] = { __VA_ARGS__ };      \ 
     log _log(__FUNCTION__, p, (sizeof p)/(sizeof p[0])); \ 
    } while (0) 

Un par de notas:

  1. __VA_ARGS__ es el nombre de la lista de argumentos separados por comas suministrados a la macro
  2. Puede averiguar cuántos hay en su caso usando sizeof ya que p es una matriz estática
  3. Sur redondear el código de macro en do..while a menudo se considera una buena práctica porque da a las variables (p) un alcance de bloque para que los usuarios puedan tener una variable con el mismo nombre fuera de la macro, y la parte while (0) acepta un punto y coma después, sin romper una línea si las declaraciones

Si necesitan más flexibilidad que esto, se puede utilizar un truco muy aseado que le permite explícitamente "sobrecarga" que la macro se comporta de forma completamente diferente con un número diferente de parámetros. Sin embargo, esto hace que el código sea mucho más intrincado y solo debe usarse si es absolutamente necesario. Dado que parece que los argumentos variados funcionarán bien para su caso de uso, proporcionaré un enlace: http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/

+0

+1 para la nota 'do while' – tangrs

+1

Obviamente, solo un error tipográfico, pero la macro se expande para simplemente' do {'. El resto de las líneas, excepto la última, necesitan ser recortadas también. – ahcox

+0

@ahcox gracias, corregido! –

14

Es posible utilizar el estándar de C/C++ args variadic en macros, al menos en gcc (EDIT: al parecer, están estandarizados, y MS compilador de C also has them) .

Consulte this page para obtener información sobre cómo funciona esto.

También hay another question en este sitio que puede ser útil para usted.

+5

Las macros de variables se estandarizaron en C99 y C++ 11: http://en.wikipedia.org/wiki/Variadic_macro – Thomas

+2

También se admite en C++ 11: "Si hay un' ... 'en el identificador- lista en la definición de macro, luego los argumentos finales, incluidos los tokens de preprocesamiento de coma de separación, se fusionan para formar un único elemento: los argumentos variables. El número de argumentos así combinados es tal que, después de la fusión, el número de argumentos es uno más que el número de parámetros en la definición de macro ".." Un identificador '__VA_ARGS__' que aparece en la lista de reemplazo se tratará como si fuera un parámetro, y los argumentos variables formarán los tokens de preprocesamiento utilizados para reemplazarlo." –