Простой сплиттер Spirit X3 не будет компилироваться, несоответствие атрибутов - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь использовать анализатор Spirit X3 для обработки вывода из инструмента командной строки, но у меня возникли проблемы. Я сузил их до минимального примера, поведение которого я не понимаю:

#include <string>
#include <vector>
#include <boost/spirit/home/x3.hpp>

int main() {
    namespace x3 = boost::spirit::x3;

    std::wstring const str = L"bonjour je suis un  petit panda";

    auto word = x3::lexeme[+x3::alpha];

    std::wstring s;
    x3::phrase_parse(begin(str), end(str), word, x3::space, s); // OK

    std::vector<std::wstring> v;
    x3::phrase_parse(begin(str), end(str), *word, x3::space, v); // Compiler error
}

Живая демоверсия на Coliru

Ошибка очень волосатая, но сводится к невозможности вызова move_to, что является признаком несоответствия типов атрибута IIUC.

/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:180:9: error: no matching function for call to 'move_to'
        detail::move_to(std::move(src), dest
        ^~~~~~~~~~~~~~~

[...]

/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:56:9: note: candidate function not viable: no known conversion from 'typename attribute_category<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > >::type' (aka 'boost::spirit::x3::traits::container_attribute') to 'boost::spirit::x3::traits::unused_attribute' for 3rd argument
        move_to(Source&&, Dest&, unused_attribute) {}
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:74:9: note: candidate function not viable: no known conversion from 'typename attribute_category<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > >::type' (aka 'boost::spirit::x3::traits::container_attribute') to 'boost::spirit::x3::traits::plain_attribute' for 3rd argument
        move_to(Source&& src, Dest& dest, plain_attribute)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:97:9: note: candidate function not viable: no known conversion from 'typename attribute_category<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > >::type' (aka 'boost::spirit::x3::traits::container_attribute') to 'boost::spirit::x3::traits::tuple_attribute' for 3rd argument
        move_to(Source&& src, Dest& dest, tuple_attribute)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:106:9: note: candidate function not viable: no known conversion from 'typename attribute_category<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > >::type' (aka 'boost::spirit::x3::traits::container_attribute') to 'boost::spirit::x3::traits::tuple_attribute' for 3rd argument
        move_to(Source&& src, Dest& dest, tuple_attribute)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:150:9: note: candidate function not viable: no known conversion from 'typename attribute_category<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > >::type' (aka 'boost::spirit::x3::traits::container_attribute') to 'boost::spirit::x3::traits::variant_attribute' for 3rd argument
        move_to(Source&& src, Dest& dest, variant_attribute tag)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:85:35: note: candidate template ignored: disabled by 'enable_if' [with Source = const wchar_t, Dest = std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >]
        inline typename enable_if<is_container<Source>>::type
                                  ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:113:9: note: candidate function template not viable: requires 4 arguments, but 3 were provided
        move_to(Source&& src, Dest& dest, variant_attribute, mpl::false_)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:143:9: note: candidate function template not viable: requires 4 arguments, but 3 were provided
        move_to(Source&& src, Dest& dest, variant_attribute, mpl::true_)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:157:9: note: candidate function template not viable: requires 4 arguments, but 3 were provided
        move_to(Iterator, Iterator, unused_type, unused_attribute) {}
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:161:9: note: candidate function template not viable: requires 4 arguments, but 3 were provided
        move_to(Iterator first, Iterator last, Dest& dest, container_attribute)
        ^
/usr/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:171:9: note: candidate function template not viable: requires 4 arguments, but 3 were provided
        move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, container_attribute)
        ^

Моя цель - разбить слово по пробелам. Парсер word возвращает первое полное слово в std::string, как и ожидалось. Почему *word не совместим напрямую с std::vector<std::string>, и что я должен вместо этого написать?

1 Ответ

0 голосов
/ 29 августа 2018

Я не уверен, что это на самом деле должно работать даже для первого случая.

Вы используете ASCII-версию синтаксических анализаторов символов (x3::alpha является синонимом x3::standard::alpha), переданный тип значения итератора равен wchar_t, но boost::spirit::char_encoding::standard::ischar() возвращает false для символов, отличных от ascii.

С x3::standard_wide::alpha работает:

#include <string>
#include <vector>
#include <boost/spirit/home/x3.hpp>

int main() {
    namespace x3 = boost::spirit::x3;

    std::wstring const str = L"bonjour je suis un  petit panda";

    auto word = x3::lexeme[+x3::standard_wide::alpha];

    std::wstring s;
    x3::phrase_parse(begin(str), end(str), word, x3::space, s); // OK

    std::vector<std::wstring> v;
    x3::phrase_parse(begin(str), end(str), *word, x3::space, v); // OK
}

Еще один хороший вопрос, должен ли он работать со шкипером ASCII, и если есть разница между x3::standard::space и x3::standard_wide::space (широкая, из-за Unicode можно рассматривать больше символов как пробелы).

...