2012-05-08 67 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看起来对我的另一个项目很感兴趣! –