问题在底部以粗体显示,该问题在结尾处也用蒸馏代码片段加以概括。
我正在尝试将我的类型系统(类型系统从类型到字符串,从类型到字符串)统一为一个组件(由Lakos定义)。我正在使用boost::array
,boost::variant
和boost::mpl
,以实现此目的。我想将我的类型的解析器和生成器规则统一在一个变量中。有一个未定义的类型,一个int4(见下文)类型和一个int8类型。变体读取为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页的错误,我终于设法找到了它,operator=
在分配期间使用了Variant ,并且boost::spirit::qi::int_parser<>
不能将a分配给另一个(operator =)。
相比之下,我的未定义类型没有问题:
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();
}
具体的解析器和规则之间存在语义鸿沟。此刻我的大脑在抽烟,所以我不会考虑实用主义,我的问题是,如何解决这个问题? 我可以想到三种解决问题的方法。
一:静态函数成员:
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;
}
};
我猜想一种方法可以防止线程安全代码??
二:整数解析器包装在shared_ptr中。我为打字系统而烦恼的原因有两个:1效率,2将关注点集中到组件中。使用指针失败了第一个原因。
三: operator =定义为无操作。变体保证lhs
在分配之前默认构造。
编辑: 我认为选项3最有意义(operator =是no-op)。一旦创建了规则容器,它就不会更改,而我只是分配以强制将类型的规则特征插入其偏移量。
parser_int32_t
情况下,选项1才是线程不安全的:具有状态并获取引用。如果是无状态的或进行了复制,则它是安全的。从语义上讲,我会说是一个副本。