Click to See Complete Forum and Search --> : macro tricks


g3RC4n
March 11th, 2008, 07:26 PM
i was wondering if it was possible to do this?


#define print_code(line) line cout << quote line quote << endl;
#define quote "

print_code(true;)


to be macroed to


true; cout << "true;" << endl;


how could i do this? just curiouse :)

thanks

UPDATE SOLVED


#define print_code(line) line cout << #line << endl;

GNiewerth
March 12th, 2008, 03:48 AM
That´s funny, yesterday I was looking for some debug helper macros because my compiler offers none and I really miss Microsoft´s debug macros. I found two interesting articles, combined them, and came up with this solution. It automatically detects the file and line number, prepends them to the message and prints the message in my debug console. Modifications may be necessary for different compilers, mine catches debugger messages yield by OutputDebugString and prints them in a separate console.


#ifndef VCLTraceH
#define VCLTraceH

#ifdef NDEBUG
#define TRACE (void)0
#else
#define TRACE VCLTrace(__FILE__,__LINE__)

class VCLTrace
{
std::string File;
unsigned int Line;

public:
VCLTrace( const char* pszFile, unsigned int uiLine ) :
File( pszFile ),
Line( uiLine )
{
}

template<typename T1>
void operator()( const T1& op1 )
{
std::ostringstream os;
os << op1;
trace( os.str() );
}

template<
typename T1, typename T2>
void operator()( const T1& op1, const T2& op2 )
{
std::ostringstream os;
os << op1 << op2;
trace( os.str() );
}


template<
typename T1, typename T2, typename T3>
void operator()( const T1& op1, const T2& op2, const T3& op3 )
{
std::ostringstream os;
os << op1 << op2 << op3;
trace( os.str() );
}

template<
typename T1, typename T2, typename T3, typename T4>
void operator()( const T1& op1, const T2& op2, const T3& op3, const T4& op4 )
{
std::ostringstream os;
os << op1 << op2 << op3 << op4;
trace( os.str() );
}

template<
typename T1, typename T2, typename T3, typename T4, typename T5>
void operator()( const T1& op1, const T2& op2, const T3& op3, const T4& op4, const T5& op5 )
{
std::ostringstream os;
os << op1 << op2 << op3 << op4 << op5;
trace( os.str() );
}

private:
void trace( const std::string& strMessage )
{
std::ostringstream os;
os << File << "(" << Line << "): " << strMessage;
OutputDebugString( os.str().c_str() );
}
};
#endif


Macro usage:


int main()
{
int a = 10;
double b = 3.5;
TRACE( "Welcome to the show, int a=", a, " and double b=", b );
}

JohnW@Wessex
March 12th, 2008, 04:57 AM
That's a very good idea!
A neat demostration of using templates too. :thumb:

(I'd rate your post but the system won't let me until I rate someone else first)

Richard.J
March 12th, 2008, 03:53 PM
the disadvantage is that you limit yourself to a max of 4 different parameters.
In my opinion, a set of embracing macros such as
TRACE << "all of tracing done here via operator<<" << TRACE_END
would be much better.
I use that in all of my code.
something like this:

#define TRACE_BASE(pp_tracer, pp_traceMode) \
try \
{ \
if(pp_tracer.isTracing(pp_traceMode)) \
{ \
Tracer& xx_tracer = pp_tracer; \
TraceMode xx_traceMode = pp_traceMode; \
std::ostringstream xx_os_yy_1234;

#define TRACE_END \
std::endl; \
xx_tracer.trace( __FILE__, __LINE__, xx_traceMode, xx_os_yy_1234 ); \
} \
} \
catch(...) {}


I must admit that I don't have a snippet ready to demonstrate the use of these macros, but they may give a notion of what is done ...

What I really hate is a set of macros that limits the user to a certain (arbitrary) value of trace "parameters".

GNiewerth
March 13th, 2008, 05:38 AM
the disadvantage is that you limit yourself to a max of 4 different parameters.
In my opinion, a set of embracing macros such as
TRACE << "all of tracing done here via operator<<" << TRACE_END
would be much better.
I use that in all of my code.
something like this:

#define TRACE_BASE(pp_tracer, pp_traceMode) \
try \
{ \
if(pp_tracer.isTracing(pp_traceMode)) \
{ \
Tracer& xx_tracer = pp_tracer; \
TraceMode xx_traceMode = pp_traceMode; \
std::ostringstream xx_os_yy_1234;

#define TRACE_END \
std::endl; \
xx_tracer.trace( __FILE__, __LINE__, xx_traceMode, xx_os_yy_1234 ); \
} \
} \
catch(...) {}


I must admit that I don't have a snippet ready to demonstrate the use of these macros, but they may give a notion of what is done ...

What I really hate is a set of macros that limits the user to a certain (arbitrary) value of trace "parameters".

Touchee... updated my macro to handle any number of parameters. Interestingly the resulting code is smaller than the one handling 4 parameters :)


#include <string>
#include <sstream>
#include <iostream>

#ifdef NDEBUG
#define TRACE VCLTrace(__FILE__,__LINE__),
#else
#define TRACE (void)0,
#endif

struct VCLTraceItem
{
std::string m_strItem;

template<typename T>
VCLTraceItem( const T& op )
{
std::ostringstream oss;
oss << op;
m_strItem = oss.str();
}
};

class VCLTrace
{
std::string m_strTraceLine;
public:
VCLTrace( const char* pszFile, unsigned int uiLine )
{
std::ostringstream oss;
oss << pszFile << " (" << uiLine << ") :";
m_strTraceLine = oss.str();
}

~VCLTrace()
{
OutputDebugString( m_strTraceLine.c_str() );
}

VCLTrace& operator,( const VCLTraceItem& op )
{
m_strTraceLine += op.m_strItem;
return *this;
}
};

int main()
{
int a = 10;
double d = 3.5;
bool b = true;
std::string s = "STRING";

TRACE "This is a test, a=", a, ", b=", b, ", s= ", s, ", d=", d;
}

treuss
March 13th, 2008, 06:40 AM
Just wanted to write that C++ 0x will add variadic arguments to templates. Thus in the future there will be a way to write this cleaner. Something like:class Trace
{
public:
template<typename... Args>
Trace(const char* file, unsigned int line, Args... args) {
s << file << '(' << line << "):";
trace(args);
std::cout << s;
}
private:
ostringstream s;

template<typename T, typename... Args>
void trace(T value, Args... args) {
s << value;
trace(args);
}

void trace() {};
}

#define TRACE(...) Trace(__FILE__, __LINE__, __VA_ARGS__)