I was assigned the task of updating a very old project a while back. The first thing I had to do was to expand the existing code to incorporate a new feature. As part of this I modified existing macros to print JSON representations of incoming messages (over CORBA, into C++ structs). I then incorporated boost program_options and a new logger and now I want to modernise the macros.
The problem is that I have no idea how to implement what I did with the macros with templates. The key problem is that I use the name of the parameters to the macros to access the fields of the struct:
//Defines the string that precedes the variable name in a JSON name-value pair (newline,indent,")
#define JSON_PRE_VNAME _T("%s,\n\t\t\t\t\"")
//Defines the string that follows the variable name in a JSON name-value pair (":) preceding the value
#define JSON_SEP _T("\":")
#define printHex(Y,X) _tprintf(_T("%02X"), (unsigned char)##Y->##X );
// ******** MACRO **********
// printParam (StructureFieldName=X, ParamType=Y)
// prints out a json key value pair.
// e.g. printParam(AgentId, %s) will print "AgentId":"3910"
// e.g. printParam(TempAgent, %d) will print "TempAgent":1
#define printParam(X,Y) if(strcmp(#Y,"%s")==0){\
_byteCount += _stprintf(_logBuf,JSON_PRE_VNAME _T(#X) JSON_SEP _T("\"%s\""),_logBuf,myEvent->##X);\
}else{\
_byteCount += _stprintf(_logBuf,JSON_PRE_VNAME _T(#X) JSON_SEP _T(#Y),_logBuf,myEvent->##X);\
}\
printBufToLog();
And it is used like this:
//CORBA EVENT AS STRUCT "event"
else if(event.type == NI_eventSendInformationToHost ){
evSendInformationToHost *myEvent;
event.data >>= myEvent; //demarshall
printParam(EventTime,%d);
printParam(Id,%d);
printParam(NodeId,%d);
}
and this results in JSON like this:
“EventTime”:1299239194,
“Id”:1234567,
“NodeId”:3
etc…
Obviously I have commented these macros fairly well, but I am hoping that for the sake of anyone else looking at the code that there is a nice way to achieve the same result with templates. I have to say the macros do make it very easy to add new events to the message logger.
Basically how do I do “#X” and ##X with templates?
Any pointers would be appreciated.
Thanks!
There are some things that you cannot really do without macros, and for some specific contexts macros are the solution. I would just leave the macros as they are and move on to the next task.
Well, I would actually try to improve a bit the macros. It is usually recommended not to use
;inside macros, and with macros that contain more than a single statement wrap them indo {} while(0)loops:This might help avoid small mistakes that would otherwise be hard to fix, as, for example uses of the macros with
if:Similarly
would expand to a whole lot of non-sense for the compiler even if it looks correct enough to the casual eye.