A few days ago, I saw this discussion on the csdn Forum: how to use variable parameters in macro definition? Http://expert.csdn.net/Expert/topic/2925/2925165.xml ). The owner hopes to define macro as follows:
# Define fun1 (a, B,...) fun2 (_ file __, _ line __, a, B ,...)
I guess the main idea is to write trace. If you cannot use macro with variable parameters, you have to write a bunch of Trace macros like MFC:
// Afx. h from MFC 7.1
// The following trace macros are provided for backward compatiblity
// (They also take a fixed number of parameters which provides
// Some amount of extra error checking)
# Define trace0 (sz) trace (_ T ("% s"), _ T (sz ))
# Define trace1 (SZ, P1) trace (_ T (sz), P1)
# Define trace2 (SZ, P1, P2) trace (_ T (sz), P1, P2)
# Define trace3 (SZ, P1, P2, P3) trace (_ T (sz), P1, P2, P3)
Too ugly! Fortunately, the c99 standard supports variadic macros, which can be written in GCC as follows:
// Http://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html
# Define debug (format,...) fprintf (stderr, format, _ va_args __)
You can also print the file name and row number by the way:
# Define debug (format,...) do {/
Fprintf (stderr, "% s (% d):", _ file __, _ line __);/
Fprintf (stderr, format, _ va_args __);/
} While (0)
However, Visual C ++ 7.1 does not support this function yet: (however, we can at least bend around in C ++ to automatically record file names and row numbers, you can also use the variable length parameter. This method is not my original one. In fact, the atltrace of ATL. h has its implementation (ctracefileandlineinfo class), I found the same implementation (http://www.codeproject.com/debug/location_trace.asp) in the Code project ), even in cuj C ++ Experts Forum can also see similar practices (http://www.cuj.com/documents/s=8250/cujcexp2106alexandr/), of course, Alexandrescu approach more skillful.
Idea: Write a class with operator () reloaded, so that the trace macro returns an object of the class:
# Include
# Include
# Ifndef ndebug // debug mode
Class Tracer
{
Public:
Tracer (const char * file, int line)
: File _ (file), line _ (line)
{}
Void operator () (const char * FMT ,...)
{
Va_list AP;
// Print the file name and line number
Fprintf (stderr, "% s (% d):", file _, line _);
Va_start (AP, FMT );
Vfprintf (stderr, FMT, AP );
Va_end (AP );
Fprintf (stderr, "/R/N"); // print the New-Line Character
}
PRIVATE:
// Copy-ctor and operator =
Tracer (const tracer &);
Tracer & operator = (const tracer &);
PRIVATE:
Const char * file _;
Int line _;
};
# Define trace (tracer (_ file __, _ line __))
# Else // ndebug
# Define trace (void)
# Endif // ndebug
Int main ()
{
# Ifndef ndebug
Tracer (_ file __, _ line _) ("% x", 123 );
# Endif
Trace ("% s", "Happy debugging .");
}
This is done in multithreading-safe mode. G ++ 3.3.1/Visual C ++ 7.1/Borland C ++ 5.5.1.