c++ - 将 JSON 日志记录宏转换为模板函数...代码中需要的参数名称

标签 c++ templates visual-c++ macros

不久前,我被分配了更新一个非常旧的项目的任务。我必须做的第一件事是扩展现有代码以包含新功能。作为其中的一部分,我修改了现有的宏以打印传入消息的 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/

相关文章:

c++ - 用于重新排序无符号整数的 Constexpr 变量模板

c++ - 将控制台应用程序变成服务?

c++ - 如何根据命中的另一个断点添加条件中断?视觉C++

c++ - 二维框架 C++

c++ - 调用 clear() 后 vector 的元素仍然可以引用?

c++ - 段错误 : 11; range-based for loop

c++ - 如何生成伪随机 32 字节字符串以用作加密哈希函数中的盐?

c++ - 混合术语

HTML 标签内的 Javascript

visual-c++ - Visual C++ boolean 错误