parsingr le vecteur en utilisant boost :: spirit :: x3

Ceci est une question complémentaire à ma précédente concernant boost::spirit::x3 et boost::ssortingng_view .

Bien que je puisse parsingr dans un std::vector ( exemple vivant ), l’parsing dans un std::vector échoue avec les erreurs de compilation suivantes:

 #include  #include  #include  namespace boost { namespace spirit { namespace x3 { namespace traits { template  void move_to(It b, It e, boost::ssortingng_view& v) { v = boost::ssortingng_view(b, std::size_t(std::distance(b,e))); } } } } } // namespace boost #include  namespace parser { namespace x3 = boost::spirit::x3; using x3::char_; using x3::raw; const auto str_vec = *(raw[ +~char_('_')] >> '_'); } int main() { std::ssortingng input = "hello_world_"; std::vector strVec; parse(input.data(), input.data()+input.size(), parser::str_vec, strVec); for(auto& x : strVec) { std::cout << x << std::endl; } } 

 In file included from /usr/local/include/c++/6.1.0/bits/stl_tempbuf.h:60:0, from /usr/local/include/c++/6.1.0/bits/stl_algo.h:62, from /usr/local/include/c++/6.1.0/algorithm:62, from /usr/local/include/boost/utility/ssortingng_view.hpp:27, from main.cpp:4: /usr/local/include/c++/6.1.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = boost::basic_ssortingng_view<char, std::char_traits >; _Args = {const char&}]': /usr/local/include/c++/6.1.0/bits/stl_uninitialized.h:75:18: required from 'static _ForwardIterator std::__uninitialized_copy::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*; _ForwardIterator = boost::basic_ssortingng_view<char, std::char_traits >*; bool _TrivialValueTypes = false]' /usr/local/include/c++/6.1.0/bits/stl_uninitialized.h:126:15: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*; _ForwardIterator = boost::basic_ssortingng_view<char, std::char_traits >*]' /usr/local/include/c++/6.1.0/bits/stl_uninitialized.h:281:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator&) [with _InputIterator = const char*; _ForwardIterator = boost::basic_ssortingng_view<char, std::char_traits >*; _Tp = boost::basic_ssortingng_view<char, std::char_traits >]' /usr/local/include/c++/6.1.0/bits/stl_vector.h:1288:33: required from 'void std::vector::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_ssortingng_view<char, std::char_traits >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/c++/6.1.0/bits/stl_vector.h:1261:4: required from 'void std::vector::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_ssortingng_view<char, std::char_traits >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/c++/6.1.0/bits/stl_vector.h:406:11: [ skipping 9 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] /usr/local/include/boost/spirit/home/x3/operator/detail/sequence.hpp:496:24: required from 'static bool boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) [with Iterator = const char*; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >; Right = boost::spirit::x3::literal_char; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence, Context, RContext>::parser_type = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >]' /usr/local/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:287:74: required from 'bool boost::spirit::x3::detail::parse_into_container(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) [with Parser = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48: required from 'bool boost::spirit::x3::kleene::parse(Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >; Subject = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >]' /usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68: required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Atsortingbute&) [with Iterator = const char*; Parser = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char > >; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26: required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Atsortingbute&) [with Iterator = const char*; Parser = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char > >; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' main.cpp:36:75: required from here /usr/local/include/c++/6.1.0/bits/stl_construct.h:75:7: error: no matching function for call to 'boost::basic_ssortingng_view<char, std::char_traits >::basic_ssortingng_view(const char&)' { ::new(static_cast(__p)) _T1(std::forward(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from main.cpp:4:0: /usr/local/include/boost/utility/ssortingng_view.hpp:82:23: note: candidate: constexpr boost::basic_ssortingng_view::basic_ssortingng_view(const charT*) [with charT = char; traits = std::char_traits]  BOOST_CONSTEXPR basic_ssortingng_view(const charT* str) ^~~~~~~~~~~~~~~~~ /usr/local/include/boost/utility/ssortingng_view.hpp:82:23: note: conversion of argument 1 would be ill-formed: In file included from /usr/local/include/c++/6.1.0/bits/stl_tempbuf.h:60:0, from /usr/local/include/c++/6.1.0/bits/stl_algo.h:62, from /usr/local/include/c++/6.1.0/algorithm:62, from /usr/local/include/boost/utility/ssortingng_view.hpp:27, from main.cpp:4: /usr/local/include/c++/6.1.0/bits/stl_construct.h:75:7: error: invalid conversion from 'char' to 'const char*' [-fpermissive] { ::new(static_cast(__p)) _T1(std::forward(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from main.cpp:4:0: /usr/local/include/boost/utility/ssortingng_view.hpp:85:23: note: candidate: constexpr boost::basic_ssortingng_view::basic_ssortingng_view(const charT*, boost::basic_ssortingng_view::size_type) [with charT = char; traits = std::char_traits; boost::basic_ssortingng_view::size_type = long unsigned int] BOOST_CONSTEXPR basic_ssortingng_view(const charT* str, size_type len) ^~~~~~~~~~~~~~~~~ /usr/local/include/boost/utility/ssortingng_view.hpp:85:23: note: candidate expects 2 arguments, 1 provided /usr/local/include/boost/utility/ssortingng_view.hpp:78:9: note: candidate: template boost::basic_ssortingng_view::basic_ssortingng_view(const std::__cxx11::basic_ssortingng&) basic_ssortingng_view(const std::basic_ssortingng<charT, traits, ^~~~~~~~~~~~~~~~~ /usr/local/include/boost/utility/string_view.hpp:78:9: note: template argument deduction/substitution failed: In file included from /usr/local/include/c++/6.1.0/bits/stl_tempbuf.h:60:0, from /usr/local/include/c++/6.1.0/bits/stl_algo.h:62, from /usr/local/include/c++/6.1.0/algorithm:62, from /usr/local/include/boost/utility/string_view.hpp:27, from main.cpp:4: /usr/local/include/c++/6.1.0/bits/stl_construct.h:75:7: note: mismatched types 'const std::__cxx11::basic_string<char, std::char_traits, Allocator>' and 'const char' { ::new(static_cast(__p)) _T1(std::forward(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from main.cpp:4:0: /usr/local/include/boost/utility/ssortingng_view.hpp:68:23: note: candidate: constexpr boost::basic_ssortingng_view::basic_ssortingng_view(const boost::basic_ssortingng_view&) [with charT = char; traits = std::char_traits] BOOST_CONSTEXPR basic_ssortingng_view(const basic_ssortingng_view &rhs) BOOST_NOEXCEPT ^~~~~~~~~~~~~~~~~ /usr/local/include/boost/utility/ssortingng_view.hpp:68:23: note: no known conversion for argument 1 from 'const char' to 'const boost::basic_ssortingng_view<char, std::char_traits >&' /usr/local/include/boost/utility/ssortingng_view.hpp:65:23: note: candidate: constexpr boost::basic_ssortingng_view::basic_ssortingng_view() [with charT = char; traits = std::char_traits] BOOST_CONSTEXPR basic_ssortingng_view() BOOST_NOEXCEPT ^~~~~~~~~~~~~~~~~ /usr/local/include/boost/utility/ssortingng_view.hpp:65:23: note: candidate expects 0 arguments, 1 provided In file included from /usr/local/include/c++/6.1.0/bits/char_traits.h:39:0, from /usr/local/include/c++/6.1.0/ios:40, from /usr/local/include/c++/6.1.0/ostream:38, from /usr/local/include/c++/6.1.0/iostream:39, from main.cpp:1: /usr/local/include/c++/6.1.0/bits/stl_algobase.h: In instantiation of 'static _OI std::__copy_move::__copy_m(_II, _II, _OI) [with _II = const char*; _OI = boost::basic_ssortingng_view<char, std::char_traits >*]': /usr/local/include/c++/6.1.0/bits/stl_algobase.h:386:44: required from '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = boost::basic_ssortingng_view<char, std::char_traits >*]' /usr/local/include/c++/6.1.0/bits/stl_algobase.h:422:45: required from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits >*, std::vector<boost::basic_string_view<char, std::char_traits > > >]' /usr/local/include/c++/6.1.0/bits/stl_algobase.h:455:8: required from '_OI std::copy(_II, _II, _OI) [with _II = const char*; _OI = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits >*, std::vector<boost::basic_string_view<char, std::char_traits > > >]' /usr/local/include/c++/6.1.0/bits/vector.tcc:637:16: required from 'void std::vector::_M_range_insert(std::vector::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_ssortingng_view<char, std::char_traits >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits > >; std::vector::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits >*, std::vector<boost::basic_string_view<char, std::char_traits > > >; typename std::_Vector_base::pointer = boost::basic_ssortingng_view<char, std::char_traits >*]' /usr/local/include/c++/6.1.0/bits/stl_vector.h:1375:4: required from 'void std::vector::_M_insert_dispatch(std::vector::iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_ssortingng_view<char, std::char_traits >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits > >; std::vector::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits >*, std::vector<boost::basic_string_view<char, std::char_traits > > >; typename std::_Vector_base::pointer = boost::basic_ssortingng_view<char, std::char_traits >*]' /usr/local/include/c++/6.1.0/bits/stl_vector.h:1100:4: [ skipping 12 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] /usr/local/include/boost/spirit/home/x3/operator/detail/sequence.hpp:496:24: required from 'static bool boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) [with Iterator = const char*; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >; Right = boost::spirit::x3::literal_char; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence, Context, RContext>::parser_type = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >]' /usr/local/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:287:74: required from 'bool boost::spirit::x3::detail::parse_into_container(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) [with Parser = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48: required from 'bool boost::spirit::x3::kleene::parse(Iterator&, const Iterator&, const Context&, RContext&, Atsortingbute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >; Subject = boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char >]' /usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68: required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Atsortingbute&) [with Iterator = const char*; Parser = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char > >; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' /usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26: required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Atsortingbute&) [with Iterator = const char*; Parser = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char > > >, boost::spirit::x3::literal_char > >; Atsortingbute = std::vector<boost::basic_string_view<char, std::char_traits > >]' main.cpp:36:75: required from here /usr/local/include/c++/6.1.0/bits/stl_algobase.h:324:18: error: no match for 'operator=' (operand types are 'boost::basic_ssortingng_view<char, std::char_traits >' and 'const char') *__result = *__first; ~~~~~~~~~~^~~~~~~~~~ In file included from main.cpp:4:0: /usr/local/include/boost/utility/ssortingng_view.hpp:71:26: note: candidate: boost::basic_ssortingng_view& boost::basic_ssortingng_view::operator=(const boost::basic_ssortingng_view&) [with charT = char; traits = std::char_traits] basic_ssortingng_view& operator=(const basic_ssortingng_view &rhs) BOOST_NOEXCEPT { ^~~~~~~~ /usr/local/include/boost/utility/ssortingng_view.hpp:71:26: note: no known conversion for argument 1 from 'const char' to 'const boost::basic_ssortingng_view<char, std::char_traits >&' 

exemple en direct

Qu’est-ce que j’oublie ici?

En surchargeant / en spécialisant move_to vous move_to gros à X3 comment convertir un boost::iterator_range (en fait juste une paire d’iterators) en boost::ssortingng_view . Malheureusement, il ne sait pas que les deux sont “équivalents” (l’un se substitute l’autre semble être la nomenclature utilisée dans Spirit). Ainsi, votre exemple d’origine fonctionne car vous demandez explicitement la transformation d’iterators en ssortingng_view mais celle-ci échoue car X3 ne dispose pas des informations requirejses pour déduire le type d’atsortingbut approprié.

En particulier, le problème semble être ici , où il est testé si l’atsortingbut de l’parsingur (dans ce cas, raw_atsortingbute_type ) est compatible avec le value_type de l’atsortingbut attendu ( boost::ssortingng_view ). Ce test échoue et un chemin de code où l’atsortingbut n’est pas “transmis tel quel” est choisi, ce qui provoque l’erreur que vous obtenez.

Cela dit, il semble y avoir deux approches possibles: soit demander explicitement la transformation, soit fournir à Spirit des informations sur la compatibilité des atsortingbuts.

Certains des attr_cast dans Qi ( attr_cast , en as[] ) semblent attr_cast que le moyen de forcer une transformation d’atsortingbut dans X3 consiste à créer une règle supplémentaire avec le type réel souhaité:

 x3::rule str= x3::raw[ +~char_('_')] >> '_'; auto const str_vec = *str; 

Vous pouvez aussi (surtout si vous avez besoin de faire cela dans plusieurs règles) utiliser une approche que j’ai vue voir utiliser plusieurs fois (comme ici ) qui crée un modèle de variable lambda qui peut être utilisé comme as(parser) qui cache la création de cette règle supplémentaire et force l’atsortingbut de l’ parser à se transformer en T

 template auto as = [](auto p) { return rule{} = as_parser(p); }; auto const str_vec = *as(x3::raw[ +~char_('_')] >> '_'); 

La manière de fournir à Spirit des informations sur la compatibilité des atsortingbuts semble être de spécialiser x3::traits::is_substitute :

 namespace boost { namespace spirit { namespace x3 { namespace traits { template <> struct is_substitute : boost::mpl::true_ {}; }}} } 

Mais comme vous l’avez mentionné dans les commentaires, cela ne semble pas être un sharepoint personnalisation documenté et je ne suis donc pas sûr que ce soit une bonne idée de l’utiliser. Idéalement, cela serait spécialisé par défaut dans X3, mais comme indiqué dans la question précédente , le fait que le stockage mentionné par les iterators doit être contigu complique la situation.