質問は下部に太字で示されています。問題は、最後に向かって蒸留コードフラグメントによっても要約されています。
私は自分の型システム(型システムが型から文字列へと行き来する)を単一のコンポーネント(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=
割り当て中に使用し、別のバリアントに割り当てるboost::spirit::qi::int_parser<>
ことはできません(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();
}
具体的なパーサーとルールの間にはセマンティックギャップがあります。私の脳は現在喫煙しているので、プラマティズムについては考えません。私の質問は、この問題をどのように解決するかです。 この問題を解決するための3つのアプローチが考えられます。
1つ:静的関数メンバー:
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;
}
};
アプローチ1はスレッドセーフなコードを妨げると思いますか??
二:統合パーサーはshared_ptrでラップされています。タイピングシステムでTMPに悩まされている理由は2つあります。1つは効率性、2つは懸念事項をコンポーネントに集中化することです。ポインタを使用すると、最初の理由が無効になります。
3: operator =はno-opとして定義されます。バリアントは、lhs
が割り当て前にデフォルトで構築されることを保証します。
編集: 私はオプション3が最も理にかなっていると思っています(operator =は何もしません)。ルールコンテナが作成されると、それは変更されません。タイプのルール特性をそのオフセットに強制するように割り当てるだけです。
parser_int32_t
状態があり、参照が取得されている場合。がステートレスであるか、コピーが作成されている場合、それは安全です。セマンティクスから、コピーが作成されたと言えます。