Член кортежа Boost Spirit x3 в адаптированной для слияния структуре

Следующий тестовый пример - это сокращение более крупного многофайлового парсера, отсюда несколько странный порядок объявлений и определений. Он не компилируется, и я понимаю, что std::tuple его запускает. Из документации мне кажется, что в синтезированном атрибуте должен быть std :: tuple, если присутствуют правильные включения. Что я делаю неправильно?

// -*- mode: c++; -*-

#include <iostream>
#include <tuple>

#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_tuple.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>

#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

#include <boost/spirit/include/support_istream_iterator.hpp>

namespace ast {

struct S {
    std::tuple< int, int > t;
    int i;
};

using boost::fusion::operator<<;

} // namespace ast

BOOST_FUSION_ADAPT_STRUCT (ast::S, t, i)

namespace parser {

using S_type = x3::rule< struct S_class, ast::S >;
BOOST_SPIRIT_DECLARE(S_type)

struct S_class;
const S_type S = "S";

using x3::int_;
const auto S_def = ( int_ >> int_ ) >> int_;

BOOST_SPIRIT_DEFINE(S)

struct S_class { };

} // namespace parser

template< typename Iterator >
bool parse (Iterator& iter, Iterator last, ast::S& s) {
    using x3::ascii::space;

#if 1
    return x3::phrase_parse (iter, last, parser::S, space, s);
#else
    return x3::parse (iter, last, ( x3::int_ >> x3::int_ ) >> x3::int_, s);
#endif // 0
}

int main () {
    const std::string s = "1 2 3";
    auto iter = s.begin ();

    ast::S obj;
    return !parse (iter, s.end (), obj);
}

Огромное спасибо.


person Engineerist    schedule 27.10.2019    source источник
comment
Кажется, что замена заключенной в скобки пары int на нетерминал, который синтезирует кортеж, исправляет это. Или явно синтезировать std :: tuple с помощью директивы as<...>, как показано в другом сообщении. Но до сих пор непонятно, почему он не должен работать как есть.   -  person Engineerist    schedule 27.10.2019


Ответы (1)


Это вложенная структура. Однако вы анализируете плоский синтезированный кортеж, который не соответствует структуре AST:

Другими словами, ((int, int), int) структурно несовместим с (int, (int, int)) или даже с (int, int, int), как ваше правило анализирует.

Упомянутые обходные пути помогают с принуждением атрибута отражать желаемую (и требуемую) структуру.

person sehe    schedule 27.10.2019
comment
Я думал, что заключение последовательности в скобки автоматически синтезирует tuple. То есть a >> b >> c - это квартира tuple< int, int, int >, а (a >> b) >> c - это tuple< tuple< int, int >, int >. Итак, вы говорите, что это не так, что касается скобок, в отсутствие семантических действий синтезируемый атрибут является плоским tuple. - person Engineerist; 28.10.2019
comment
да. Раньше я знал, как легко проверить синтезированный тип атрибута (см. stackoverflow.com/questions/9404189/ или более модернизированный вариант здесь stackoverflow.com/questions/58353782 /). Я думаю в X # должно быть что-то вроде aattribute_of<decltype(x3::as_parser(expression))>::type trait, но я этого раньше не понимал. - person sehe; 28.10.2019