Вопрос выделен жирным шрифтом внизу, проблема также обобщена фрагментом кода дистилляции ближе к концу.
Я пытаюсь объединить мою систему типов (система типов переходит от типа к строке и обратно) в один компонент (как определено Лакосом). Я использую 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 страниц ошибок, и мне наконец удалось отследить ее, Variant использует 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();
}
Между конкретными парсерами и правилами существует смысловой разрыв. Мой мозг в настоящее время курит, поэтому я не собираюсь думать о праматизме, У меня вопрос, как мне решить эту проблему? Я могу придумать три подхода к решению проблемы.
one: Статические функции-члены:
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;
}
};
Я полагаю, один подход предотвращает потокобезопасный код? ?
two: Интегральный синтаксический анализатор заключен в shared_ptr. Есть две причины, по которым я беспокоюсь о системе печати: 1 - эффективность, 2 - объединение проблем в компоненты. использование указателей побеждает первую причину.
three: operator = определяется как неиспользуемый. вариант гарантирует, что lhs
по умолчанию создается перед присваиванием.
Edit:
Я думаю, что вариант 3 имеет больше смысла (оператор = не работает). Как только контейнер правил создан, он не изменится, и я назначаю его только для принудительной установки черты правила типа в его смещение.