不久前,我被分配了更新一个非常旧的项目的任务。我必须做的第一件事是扩展现有代码以包含新功能。作为其中的一部分,我修改了现有的宏以打印传入消息的 JSON 表示(通过 CORBA,到 C++ 结构中)。然后我合并了 boost program_options 和一个新的记录器,现在我想使宏现代化。
问题是我不知道如何用模板实现我用宏所做的事情。关键问题是我使用宏的参数名称来访问结构的字段:
//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();
它是这样使用的:
//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);
}
这会导致像这样的 JSON:
"EventTime":1299239194, "Id":1234567, "NodeId":3
等...
很明显,我已经很好地评论了这些宏,但为了其他查看代码的人,我希望有一种很好的方法可以使用模板实现相同的结果。我不得不说宏确实让向消息记录器添加新事件变得非常容易。
基本上我如何使用模板执行“#X”和##X?
如有任何指点,我们将不胜感激。
谢谢!
最佳答案
如果没有宏,有些事情是无法真正做到的,对于某些特定的上下文,宏是解决方案。我会按原样保留宏并继续执行下一个任务。
好吧,我实际上会尝试改进一下宏。通常建议不要在宏中使用 ;
,对于包含多个语句的宏,将它们包装在 do {} while(0)
循环中:
#define printHex(Y,X) _tprintf(_T("%02X"), (unsigned char)##Y->##X )
// remove ; ^
// add do while here:
#define printParam(X,Y) do { 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();\
} while (false)
这可能有助于避免难以修复的小错误,例如将宏与 if
一起使用:
if (condition) printHex(a,b);
else printHex(c,d);
// looks good, but would originally expand to a syntax error:
if (condition) _tprintf(_T("%02X"), (unsigned char)##Y->##X );;
else ...
同理
if (condition) printParam(a,b);
else ...
对于编译器来说,即使它看起来足够正确,也会扩展成一大堆无意义的东西。
关于c++ - 将 JSON 日志记录宏转换为模板函数...代码中需要的参数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5197857/