Как я предупреждал людей раньше ¹ вы раздвигаете границы прямо на пересечении вещей, которые часто ломают механизмы Духа:
- одноэлементные последовательности слияния
- АДТ-адаптация в целом
- Постоянные ошибки с исправленным ADT в разработке ( после 1.67.0 релиза)
1. Одноэлементная головоломка
Я не буду тратить на это много времени, потому что он довольно старый, скучный, хорошо документированный ² и не имеет значения для вашего вопроса.
Давайте сделаем шаг в сторону, добавив фиктивное поле:
struct rexpr
{
rexpr_map i_entries;
const rexpr_map& entries() const { return i_entries; }
rexpr_map& entries() { return i_entries; }
void entries(const rexpr_map& ent) { i_entries = ent; }
int i_dummy;
int dummy() const { return i_dummy; }
void dummy(int i) { i_dummy = i; }
};
// ... later:
BOOST_FUSION_ADAPT_ADT(client::ast::rexpr,
(obj.entries(), obj.entries(val))
(obj.dummy(), obj.dummy(val))
)
// ... even later:
auto const rexpr_def =
'{' >> *rexpr_key_value >> '}' >> x3::attr(42);
2. ADT Proxy
Аппарат атрибута категории Spirit обнаруживает свойство entries
в качестве атрибута контейнера (is_container<...>{}
оценивается как true
).
Однако требуемые свойства контейнера отсутствуют.
Более того, из-за ограниченного интерфейса, предоставляемого прокси-серверами ADT, значения свойств могут только заменять полную продажу, а это означает, что мы можем реализовать только очень неоптимальную версию:
namespace boost { namespace spirit { namespace x3 { namespace traits {
template <typename T, auto... Other>
struct container_value<boost::fusion::extension::adt_attribute_proxy<T, Other...> >
: container_value<typename boost::fusion::extension::adt_attribute_proxy<T, Other...>::type>
{ };
template <typename T, auto... Other>
struct push_back_container<boost::fusion::extension::adt_attribute_proxy<T, Other...> >
{
using underlying_type = typename boost::fusion::extension::adt_attribute_proxy<T, Other...>::type;
template <typename X, typename Y>
static bool call(X& proxy, Y&& v) {
auto u = proxy.get();
bool b = push_back_container<underlying_type>::call(u, std::forward<Y>(v));
proxy = u;
return b;
}
};
} } } }
3. Сюрприз: старые ошибки исправлены после 1.67.0
Вы требуете коммитов:
commit ae78e1ec2431517a8b0580099aeba8f9122d8abb
Author: Nikita Kniazev <nok.raven@gmail.com>
Date: Thu Mar 15 17:33:36 2018 +0300
X3: sequence: Fixed reference to temporary bug
commit e7f31017ec7c0b5584d12ec1b718d8c415b26fa1
Author: Nikita Kniazev <nok.raven@gmail.com>
Date: Wed Mar 14 18:54:35 2018 +0300
Qi: Fixed ADT support by permutation and sequence_or operator
This is follow-up to 0f2b3c49ce55a41a7d22cc5533e0f4ba59e491ae
Они более поздние, чем 1.67.0, и в настоящее время находятся в ветке develop
. Они (частично) исправляют старую проблему: https://github.com/boostorg/spirit/pull/153#issuecomment-152879056. На текущее поведение также может повлиять коммит
commit a0df3c098ff4e42c0958796c4f47d4d72a20c164
Merge: f73b121 fac9dfa
Author: Nikita Kniazev <nok.raven@gmail.com>
Date: Thu Mar 1 13:44:27 2018 +0300
Merge pull request #370 from Kojoley/x3-pass-container-attribute-through-sequence
X3: Pass container attribute through sequence
Трудно оценить, является ли воздействие положительным или отрицательным в этом ... турбулентном ландшафте.
Демо
Достаточно сказать, что если вы
- скомпилировать против ae78e1ec243151 или новее (
develop
)
- Примените оба обходные пути, описанные выше
затем Я вижу ожидаемый результат:
-------------------------
Parsing succeeded
-------------------------
{
"color" = "blue"
"position" = {
"x" = "123"
"y" = "456"
}
"size" = "29 cm."
}
(на основе ввода libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr
).
Подведение итогов
Надеюсь, вы не думаете, что это "хорошо". Пожалуйста, рассмотрите вопрос о проблеме в списке рассылки / github. Также примите это во внимание:
¹ не говоря уже о моей неприязни к нему в большинстве случаев: Использование духа для разбора на классы?
² Проблема распространения атрибута Spirit Qi с одноэлементной структурой , X3, что такое attr_gen? , boost :: spirit :: x3 правила совместимости атрибутов, интуиция или код