I'm writing a simple macro to show TRACE information.
This is what I'm using ,
#ifdef __DEBUG__
#define TRACE { PrintErrorMsg("Trace exception at " __FILE__ "LineNo:"##(__LINE__) "Function: " __FUNCTION__ " " );}
#else
#define TRACE
#endif
This is working with FILE, but it doesn't seems to work with LINE ,
Any idea how could I deal with this. I already tried stringing operator too.Which is as
bellow.
#ifdef __DEBUG__
#define TRACE { PrintErrorMsg("Trace exception at " __FILE__ "LineNo:"#(__LINE__) "Function: " __FUNCTION__ " " );}
#else
#define TRACE
#endif
and without parms and with double parms , ex - __LINE__
or ((__LINE__))
Any idea how could I deal with this problem?
And I come up with this,
#ifdef __DEBUG__
#define ERROR_MSG_BUF_SIZE 1024
#define TRACE { char * error_msg_buffer = new char[ERROR_MSG_BUF_SIZE]; \
sprintf(error_msg_buffer,"Trace Exception at file: %s ,Line : %d , Function %s \n",__FILE__,__LINE__,__FUNCTION__);\
PrintErrorMsg(error_msg_buffer );\
delete[] error_msg_buffer;}
#else
#define TRACE
But I want to do it without using sprintf , just only by stringing and token pasting.
Any idea?
#endif
--Thanks in advance--
You need this kind of silliness, unfortunately.
#include <stdio.h>
#define TRACE2(f,l) printf("I am at file: " f " and line: " #l "\n")
#define TRACE1(f,l) TRACE2(f,l)
#define TRACE() TRACE1(__FILE__, __LINE__)
int main(void)
{
TRACE();
TRACE();
}
I am at file: test.cpp and line: 9
I am at file: test.cpp and line: 10
When you try to stringize something with #x
, that x
must be a macro parameter:
#define FOO #__LINE__ /* this is not okay */
#define BAR(x) #x /* this is okay */
But you cannot simply say BAR(__LINE__)
, because this will pass the token __LINE__
into BAR
, where it is immediately turned into a string without expansion (this is by design), giving "__LINE__"
. The same thing happens with the token-pasting operator ##
: expansion of their operands never happens.
The solution is to add indirection. You should always have these in your codebase somewhere:
#define STRINGIZE(x) STRINGIZE_SIMPLE(x)
#define STRINGIZE_SIMPLE(x) #x
#define CONCAT(first, second) CONCAT_SIMPLE(first, second)
#define CONCAT_SIMPLE(first, second) first ## second
Now STRINGIZE(__LINE__)
turns to STRINGIZE_SIMPLE(__LINE__)
which gets fully expanded to (for example) #123
, which results in "123". Phew! I leave STRINGIZE_SIMPLE
around on the off chance I want the original behavior. So your code would be something like:
#include <iostream>
#define STRINGIZE(x) STRINGIZE_SIMPLE(x)
#define STRINGIZE_SIMPLE(x) #x
#define TRACE() \
PrintErrorMsg("Trace exception in " __FILE__ \
" at line number " STRINGIZE(__LINE__) \
" in function " __FUNCTION__ ".")
void PrintErrorMsg(const char* str)
{
std::cout << str << std::endl;
}
int main()
{
TRACE();
}