2012-05-08 64 views
11

流運營商是否有自動生成的ostream < <運營商結構或類的工具嗎?自動生成結構/

輸入(從One Debug-Print function to rule them all截取):

typedef struct ReqCntrlT /* Request control record */ 
{ 
    int    connectionID; 
    int    dbApplID; 
    char   appDescr[MAX_APPDSCR]; 
    int    reqID; 
    int   resubmitFlag; 
    unsigned int resubmitNo; 
    char   VCIver[MAX_VCIVER]; 
    int    loginID; 
} ReqCntrlT; 

輸出:

std::ostream& operator <<(std::ostream& os, const ReqCntrlT& r) 
{ 
    os << "reqControl { " 
     << "\n\tconnectionID: " << r.connectionID 
     << "\n\tdbApplID: " << r.dbApplID 
     << "\n\tappDescr: " << r.appDescr 
     << "\n\treqID: " << r.reqID 
     << "\n\tresubmitFlag: " << r.resubmitFlag 
     << "\n\tresubmitNo: " << r.resubmitNo 
     << "\n\tVCIver: " << r.VCIver 
     << "\n\tloginID: " << r.loginID 
     << "\n}"; 
    return os; 
} 

任何工具就可以了,Python的/ Ruby腳本將是優選的。

+0

有人可能會嘗試自動類序列化工具,我相信助推器有一個。運營商的輸出格式對您來說有什麼格式? – johnathon

+0

JSON,XML,人類可以閱讀的任何內容都適合我。 –

+0

你*可能*可能產生它與提升PP和MPL – David

回答

0

我也明白在兩個方面你的問題。

如果你想生成程序的自動狀態報告,我建議你檢查Boost.Serialization。 然而,它不會在編譯時生成代碼作爲第一步或靈感。 下面的代碼將幫助您生成可讀取的xml或txt文件。

typedef struct ReqCntrlT /* Request control record */ 
{ 
    int    connectionID; 
    int    dbApplID; 
    char   appDescr[MAX_APPDSCR]; 
    int    reqID; 
    int   resubmitFlag; 
    unsigned int resubmitNo; 
    char   VCIver[MAX_VCIVER]; 
    int    loginID; 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar & connectionID; 
     ar & reqID; 
     ... 
    } 
} ReqCntrlT; 

詳情請參見教程:http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/index.html

如果你只是想通過只給參數名「寫」的代碼。 然後你應該看看python或perl中的正則表達式。 這個解決方案的主要缺省是你的結構是「脫機」的,即每次你改變某些東西時都必須運行它。

Benoit。

+0

主要問題是我不想自己編寫序列化方法,因爲它是枯燥乏味的工作。由於我想輸出的所有結構都很簡單,我想自動生成serialize()或operator <<()代碼。 –

1

爲了實現這一目標,唯一的辦法是使用你對你的源文件運行外部工具。

首先,你可以使用一個c/c++ analysing tool,並用它來從你的源代碼檢索分析樹。然後,一旦你得到了解析樹,你只需要搜索結構。 對於每個結構,您現在可以生成序列化結構字段的operator<<重載。您也可以生成deserialize操作符。

但是它取決於你有多少結構:對於一打就更好是手動編寫操作符,但是如果你有幾百個結構,你可能想寫(序列化)操作符生成器。

3

這是一個工具,它可以準確地解析C++,枚舉各種類/結構,確定並生成每個類/結構的「序列化」,然後將生成的代碼停放在「正確的地方「(可以發現結構的範圍相同)。它需要一個完整的預處理器來處理實際代碼中的指令擴展。

我們DMS Software Reengineering ToolkitC++11 front end可以做到這一點。 DMS通過提供通用解析/ AST構建,符號表構造,流程和自定義分析,轉換和源代碼再生能力來構建定製工具。 C++前端使DMS能夠解析C++並構建精確的符號表,以及將漂亮的打印修改或新的AST轉換回可編譯的源代碼形式。 DMS及其C++前端已被用於對C++代碼進行大規模的轉換。

你必須向DMS解釋你想做什麼;似乎很容易枚舉符號表條目,詢問是否存在結構/類類型聲明,確定聲明的範圍(記錄在符號表條目中),通過組合表面語法模式構造AST,然後應用轉換來插入構造的AST。

所需的芯體表面的語法模式是那些插槽和用於功能體:

pattern ostream_on_slot(i:IDENTIFIER):expression = 
    " << "\n\t" << \tostring\(\i\) << r.\i "; -- tostring is a function that generates "<name>" 

pattern ostream_on_struct(i:IDENTIFIER,ostream_on_slots:expression): declaration = 
    " std::ostream& operator <<(std::ostream& os, const \i& r) 
    { os << \tostring\(\i\) << " { " << \ostream_on_slots << "\n}"; 
     return os; 
    } 

一個具有以構成單獨的樹木爲ostream_on_slot:

pattern compound_ostream(e1:expression, e2:expression): expression 
    = " \e1 << \e2 "; 

有了這些圖案是簡單的枚舉struct的槽,構造主體的ostream,並將其插入結構的整體函數中。

2

主要有兩種方法可以做到這一點:

  • 使用外部分析工具(如Python腳本上鏘綁定掛鉤)
  • 使用元編程工藝

..當然它們可以混合使用。

我沒有足夠的關於Clang Python綁定的知識來回答使用它們,所以我將專注於metapogramming。


基本上,你要求的內容需要反思。 C++不支持完全自省,但是使用元編程技巧(和模板匹配),它可以在編譯時支持有限的內省技術子集,這對我們的目的來說已經足夠了。

爲了簡單地將元編程和運行時操作混合起來,更容易使庫發揮作用:Boost.Fusion

如果你調整了你的結構,使得它的屬性根據Boost.Fusion序列來描述,那麼你可以在序列中自動應用大量的算法。在這裏,associate sequence是最好的。

因爲我們所說的元編程,the map類型值一個關聯。

然後,您可以使用for_each來遍歷該序列。


我會粉飾的細節,只是因爲它已經有一段時間,我不記得的語法介入,但基本上這個想法是去:

// Can be created using Boost.Preprocessor, but makes array types a tad difficult 
DECL_ATTRIBUTES((connectionId, int) 
       (dbApplId, int) 
       (appDescr, AppDescrType) 
       ... 
       ); 

這是句法糖被宣佈融合地圖及其相關標籤:

struct connectionIdTag {}; 
struct dbApplIdTag {}; 

typedef boost::fusion::map< 
    std::pair<connectionIdTag, int>, 
    std::pair<dbApplIdTag, int>, 
    ... 
    > AttributesType; 
AttributesType _attributes; 

然後,需要在屬性應用可以用簡單的內置任何操作:

// 1. A predicate: 
struct Predicate { 
    template <typename T, typename U> 
    void operator()(std::pair<T, U> const&) const { ... } 
}; 

// 2. The for_each function 
for_each(_attributes, Predicate()); 
+0

@MatthieM:Di會喜歡外部解決方案,我粘貼該結構並按下generate,然後複製生成的操作員代碼。我想要輸出的大部分結構都在外部庫中。 –

+0

@ChristopherOezbek:我不知道任何「集成」工具(我認爲太專業),但如果你不想爲DMS支付費用(Ira的答案),那麼我建議你對Clang項目感興趣。使用libclang,你可以解析C++文件,然後在AST上運行。您可以在clang dev郵件列表中詢問具體問題。 –

+0

@MatthieM:謝謝! Boost :: Fusion看起來對我的另一個項目很感興趣! –