Tuesday, May 20, 2008

Macros and Variable Arguments in VisualStudio 2003

The preprocessor in Microsoft VisualStudio 2003 (VC++ 7.1) does not support variable argument lists in macros; instead it spews syntax errors when compiling. However, there is a way to get around this limitation and indeed gain this ability.

In a project I'm working on, we use macros to construct portions of our logging system. A typical declaration looks as such:

#define LOG_TRACE(...) log_routine(__FILE__, __LINE__, __VA_ARGS__)

However this fails to compile on VisualStudio.Net 2003, because as stated before, its preprocessor does not support variable argument lists.

A workaround is to instead use a class to handle the semantics of the variable argument list; observe:

class tracing_output_va
{
private:
const char* m_file;
int m_line;

public:
tracing_output_va(
const char* p_File,
const int p_Line) :
m_file( p_File ),
m_line( p_Line )
{

}

void operator()( const char* p_Format, ... )
{
va_list marker ;
va_start( marker, p_Format ) ;
LoggingOutVa(
m_file,
m_line,
p_Format,
marker ) ;

va_end( marker );

}
};


And then redefine the macro as such:

#define LOG_TRACE_APPLIB (tracing_output_va(__FILE__, __LINE__) )

This will indeed compile and perform as expected in VC++ 7.1

The elegance to this solution is that one need only modify the declaration of this macro, and that existing calls to this macro need not change.

For what it's worth the routine LoggingOutVa( ) wraps the actual magic of formatting and file output.


Cite: http://www.codeproject.com/KB/debug/location_trace.aspx

No comments: