更多精神疯狂 – parsing器types(规则vs int_parser <>)和元编程技术

问题是在底部粗体,问题也是由蒸馏代码片段总结的。

我试图统一我的types系统(types系统做和从types到string)到一个单一的组件(由Lakos定义)。 我正在使用boost::arrayboost::variantboost::mpl ,以实现此目的。 我希望我的types的parsing器和生成器规则统一在一个变体中。 有一个未定义的types,一个int4(见下文)types和一个int8types。 该变体读作variant<undefined, int4,int8>

int4特征:

 struct rbl_int4_parser_rule_definition { typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type; boost::spirit::qi::int_parser<rbl_int4> parser_int32_t; rule_type rule; rbl_int4_parser_rule_definition() { rule.name("rbl int4 rule"); rule = parser_int32_t; } }; template<> struct rbl_type_parser_rule<rbl_int4> { typedef rbl_int4_parser_rule_definition string_parser; }; 

上面的变种开始为未定义,然后我初始化规则。 我有一个问题,这导致了50页的错误,我终于设法追查下来,Variant在赋值时使用operator= ,而boost::spirit::qi::int_parser<>不能赋给另一个(operator = )。

相比之下,我的undefinedtypes没有问题:

 struct rbl_undefined_parser_rule_definition { typedef boost::spirit::qi::rule<std::string::iterator, void()> rule_type; rule_type rule; rbl_undefined_parser_rule_definition() { rule.name("undefined parse rule"); rule = boost::spirit::qi::eps; } }; template<> struct rbl_type_parser_rule<rbl_undefined> { typedef rbl_undefined_parser_rule_definition string_parser; }; 

问题的蒸馏:

 #include <string> #include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> #include <boost/cstdint.hpp> typedef boost::spirit::qi::rule<std::string::iterator,void()> r1; typedef boost::spirit::qi::rule<std::string::iterator,int()> r2; typedef boost::variant<r1,r2> v; int main() { /* problematic boost::spirit::qi::int_parser<int32_t> t2; boost::spirit::qi::int_parser<int32_t> t1; t1 = t2; */ //unproblematic r1 r1_; r2 r2_; r1_ = r2_; v v_; // THIS is what I need to do. v_ = r2(); } 

具体parsing器和规则之间存在语义鸿沟。 我的大脑此刻正在吸烟,所以我不会去考虑一下这个问题我的问题是,我该如何解决这个问题呢? 我可以想出三个办法来解决这个问题。

一:静态函数成员:

 struct rbl_int4_parser_rule_definition { typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type; //boost::spirit::qi::int_parser<rbl_int4> parser_int32_t; rule_type rule; rbl_int4_parser_rule_definition() { static boost::spirit::qi::int_parser<rbl_int4> parser_int32_t; rule.name("rbl int4 rule"); rule = parser_int32_t; } }; 

我想方法一,防止线程安全的代码? ?

二:整数parsing器被包装在一个shared_ptr中。 有两个原因让我在使用TMP打字系统时感到困扰:1效率,2集中关注组件。 使用指针失败的第一个原因。

三: operator =被定义为no-op。 变体保证lhs在赋值之前是默认构造的。

编辑:我想选项3最有意义(运营商=是一个没有操作)。 一旦规则容器被创build,它不会改变,我只分配强制一个types的规则特质到它的偏移量。

我不太确定我是否完全了解这个问题,但是这里有一些提示

  • 该行评论/ / // THIS is what I need to do. 编译罚款与我(问题解决?我猜你实际上是指分配一个parsing器,而不是一个规则?)

  • 在最新的标准(C ++ 11)中,函数本地static初始化被定义为线程安全的。 检查你的编译器对C ++ 0x线程的支持。 (如果初始化器抛出,初始化语句的通过将尝试再次初始化,顺便说一句)。

  • 规则alias()

    http://boost-spirit.com/home/articles/doc-addendum/faq/#aliases中所述;

    您可以创build规则的“逻辑副本”,而不必实际值复制原始expression式。 正如FAQ所说,这主要是为了允许延迟绑定

  • Nabialek技巧可能正是你所需要的,基本上它懒惰地select一个parsing器进行后续的parsing

     one = id; two = id >> ',' >> id; keyword.add ("one", &one) ("two", &two) ; start = *(keyword[_a = _1] >> lazy(*_a)); 

    在你的情况下,我可以看到keyword定义为

     qi::symbols<char, qi::rule<Iterator>*> keyword; 

    用语义行为的属性来完成所有的工作。 或者,

     qi::symbols<char, qi::rule<Iterator, std::variant<std::string,int>() >*> keyword; 
  • 把规则带到同一个types下(基本上就像上一行所示)

    这是我感到困惑的部分:你说你想统一你的types系统。 可能不需要强typesparsing器(不同的属性签名)。

     typedef boost::variant<std::string,int> unified_type; typedef qi::rule<std::string::iterator, unified_type() > unified_rule; unified_rule rstring = +(qi::char_ - '.'); unified_rule rint = qi::int_; unified_rule combine = rstring | rint;