2011-03-04 22 views
0

我被分配了更新舊項目的任務。我必須做的第一件事就是擴展現有的代碼以結合新的功能。作爲其中的一部分,我修改了現有的宏來打印傳入消息的JSON表示(通過CORBA,到C++結構中)。然後,我加入了boost program_options和一個新的記錄器,現在我想對這些宏進行現代化。將JSON記錄宏轉換爲模板函數...代碼中需要的參數名稱

問題是,我不知道如何實現我用模板做的宏。關鍵的問題是,我使用的參數爲宏的名稱來訪問該結構的字段:

//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?

任何指針,將不勝感激。

謝謝!

回答

2

有一些事情,你不能沒有宏,但對於一些特定的上下文宏的解決方案。我只想讓宏保持原樣並繼續下一個任務。

那麼,我會嘗試改善一下宏。它通常建議不要使用;內宏,以及包含超過一個聲明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 ... 

將擴大但對編譯器而言,即使它看起來對於偶然的眼睛來說是足夠正確的,也是非常重要的。

+0

第二個宏 – 6502 2011-03-04 20:33:50

+0

@ 6502上缺少'}':已更正,謝謝! – 2011-03-06 00:23:16

+0

感謝您的信息。這樣做()想法是一個很好的補充。 – Dennis 2011-03-07 08:25:20

1

我認爲在很多情況下最好使用外部代碼生成器......從一個好的中性定義開始,它很容易生成C++,Javascript和不能處理數據的東西。

C++模板是相當原始的,結構/類內省只是缺席。通過玩一些技巧,你可以做到如果和循環(哇!什麼是成就),但很多有用的技術是遙不可及的。另外,一旦你難以調試模板的欺騙性工作,在第一次錯誤時,程序員會讓你獲得喋喋不休的屏幕和屏幕,而不是一個明確的錯誤信息。

另一方面,你有C預處理器,它在做任何實際處理時都非常弱,只比正則表達式搜索/替換多一點(也少一些)。

爲什麼依附於糟糕的工具,而不是僅僅實現一個單獨的代碼生成階段(可以輕鬆地集成到make過程中),您可以使用您所選擇的嚴肅語言輕鬆完成處理和文本操作? 編寫一箇中性的易於解析的文件,然後使用例如一個Python程序來生成C++結構聲明,序列化代碼以及與之相對應的javascript對話框是多麼容易?

+0

不錯的主意,你可能會發現它。我認爲我將不得不在未來再研究一下這種可能性。我不知道爲什麼我以前從來沒有想過這是一種有效的方法。 – Dennis 2011-03-07 08:28:03