解析为vector< boost :: string_view>使用boost :: spirit :: x3 [英] parse into vector<boost::string_view> using boost::spirit::x3

查看:75
本文介绍了解析为vector< boost :: string_view>使用boost :: spirit :: x3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我>上一个问题的后续问题关于boost::spirit::x3boost::string_view.

虽然我可以解析为std::vector<std::string>(实时示例),进入std::vector<boost::string_view>失败,并出现以下编译错误:

#include <iostream>
#include <string>

#include <boost/utility/string_view.hpp>

namespace boost {
namespace spirit { namespace x3 { namespace traits {

template <typename It>
void move_to(It b, It e, boost::string_view& v)
{
    v = boost::string_view(b, std::size_t(std::distance(b,e)));
}

} } }

} // namespace boost


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

namespace parser
{
    namespace x3 = boost::spirit::x3;
    using x3::char_;
    using x3::raw;

    const auto str_vec  = *(raw[ +~char_('_')] >> '_');
}

int main()
{
    std::string input = "hello_world_";

    std::vector<boost::string_view> 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/string_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_string_view<char, std::char_traits<char> >; _Args = {const char&}]':

/usr/local/include/c++/6.1.0/bits/stl_uninitialized.h:75:18:   required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*; _ForwardIterator = boost::basic_string_view<char, std::char_traits<char> >*; 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_string_view<char, std::char_traits<char> >*]'

/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<_Tp>&) [with _InputIterator = const char*; _ForwardIterator = boost::basic_string_view<char, std::char_traits<char> >*; _Tp = boost::basic_string_view<char, std::char_traits<char> >]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1288:33:   required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1261:4:   required from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >]'

/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<L, R>, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Iterator = const char*; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, char> > > >; Right = boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>; 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<L, R>, 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/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&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48:   required from 'bool boost::spirit::x3::kleene<Subject>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68:   required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26:   required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

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_string_view<char, std::char_traits<char> >::basic_string_view(const char&)'

     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:82:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const charT*) [with charT = char; traits = std::char_traits<char>] <near match>

       BOOST_CONSTEXPR basic_string_view(const charT* str)

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_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/string_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<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:85:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const charT*, boost::basic_string_view<charT, traits>::size_type) [with charT = char; traits = std::char_traits<char>; boost::basic_string_view<charT, traits>::size_type = long unsigned int]

       BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:85:23: note:   candidate expects 2 arguments, 1 provided

/usr/local/include/boost/utility/string_view.hpp:78:9: note: candidate: template<class Allocator> boost::basic_string_view<charT, traits>::basic_string_view(const std::__cxx11::basic_string<charT, traits, Allocator>&)

         basic_string_view(const std::basic_string<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<char>, Allocator>' and 'const char'

     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:68:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const boost::basic_string_view<charT, traits>&) [with charT = char; traits = std::char_traits<char>]

       BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:68:23: note:   no known conversion for argument 1 from 'const char' to 'const boost::basic_string_view<char, std::char_traits<char> >&'

/usr/local/include/boost/utility/string_view.hpp:65:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view() [with charT = char; traits = std::char_traits<char>]

       BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_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<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = const char*; _OI = boost::basic_string_view<char, std::char_traits<char> >*]':

/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_string_view<char, std::char_traits<char> >*]'

/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<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >]'

/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<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >]'

/usr/local/include/c++/6.1.0/bits/vector.tcc:637:16:   required from 'void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = boost::basic_string_view<char, std::char_traits<char> >*]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1375:4:   required from 'void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = boost::basic_string_view<char, std::char_traits<char> >*]'

/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<L, R>, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Iterator = const char*; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, char> > > >; Right = boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>; 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<L, R>, 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/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&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48:   required from 'bool boost::spirit::x3::kleene<Subject>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68:   required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26:   required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

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_string_view<char, std::char_traits<char> >' and 'const char')

        *__result = *__first;

        ~~~~~~~~~~^~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:71:26: note: candidate: boost::basic_string_view<charT, traits>& boost::basic_string_view<charT, traits>::operator=(const boost::basic_string_view<charT, traits>&) [with charT = char; traits = std::char_traits<char>]

       basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT {

                          ^~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:71:26: note:   no known conversion for argument 1 from 'const char' to 'const boost::basic_string_view<char, std::char_traits<char> >&'

在线示例

我在这里想念什么?

解决方案

通过重载/专业化move_to,您基本上是在告诉X3如何从boost::iterator_range(实际上只是一对迭代器)转换为boost::string_view.不幸的是,它不知道两者都是等效的"(一个是substitute,另一个似乎是Spirit中使用的术语).因此,您的原始示例之所以有效,是因为您明确请求从迭代器到string_view的转换,但是由于X3缺少推断适当属性类型所需的信息,因此这一尝试失败了.

特别是问题似乎是

牢记所有这些,似乎有两种可能的方法:要么明确请求转换,要么向Spirit提供有关属性兼容性的信息.

缺少Qi中的一些助手(attr_castas[]),似乎在X3中强制进行属性转换的方法是通过使用所需的实际类型创建额外的规则:

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

您还可以(尤其是如果您需要在多个规则中执行此操作)使用一种我见过多次使用的方法(例如 here )创建一个变量模板lambda,可以像as<T>(parser)一样使用它来隐藏该额外规则的创建,并强制parser的属性转换为T.

template<typename T>
auto as = [](auto p) { return rule<struct _, T>{} = as_parser(p); };
auto const str_vec = *as<boost::string_view>(x3::raw[ +~char_('_')] >> '_');

为Spirit提供有关属性兼容性的信息的方法似乎是专门化x3::traits::is_substitute:

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

但是,正如您在评论中提到的那样,这似乎不是记录在案的自定义点,因此我不确定使用它是否是一个好主意.理想情况下,默认情况下,它在X3中是专门的,但正如sehe在previous one regarding boost::spirit::x3 and boost::string_view.

While I can parse into a std::vector<std::string> (live example), parsing into a std::vector<boost::string_view> fails with the following compile errors:

#include <iostream>
#include <string>

#include <boost/utility/string_view.hpp>

namespace boost {
namespace spirit { namespace x3 { namespace traits {

template <typename It>
void move_to(It b, It e, boost::string_view& v)
{
    v = boost::string_view(b, std::size_t(std::distance(b,e)));
}

} } }

} // namespace boost


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

namespace parser
{
    namespace x3 = boost::spirit::x3;
    using x3::char_;
    using x3::raw;

    const auto str_vec  = *(raw[ +~char_('_')] >> '_');
}

int main()
{
    std::string input = "hello_world_";

    std::vector<boost::string_view> 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/string_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_string_view<char, std::char_traits<char> >; _Args = {const char&}]':

/usr/local/include/c++/6.1.0/bits/stl_uninitialized.h:75:18:   required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*; _ForwardIterator = boost::basic_string_view<char, std::char_traits<char> >*; 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_string_view<char, std::char_traits<char> >*]'

/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<_Tp>&) [with _InputIterator = const char*; _ForwardIterator = boost::basic_string_view<char, std::char_traits<char> >*; _Tp = boost::basic_string_view<char, std::char_traits<char> >]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1288:33:   required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1261:4:   required from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >]'

/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<L, R>, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Iterator = const char*; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, char> > > >; Right = boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>; 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<L, R>, 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/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&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48:   required from 'bool boost::spirit::x3::kleene<Subject>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68:   required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26:   required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

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_string_view<char, std::char_traits<char> >::basic_string_view(const char&)'

     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:82:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const charT*) [with charT = char; traits = std::char_traits<char>] <near match>

       BOOST_CONSTEXPR basic_string_view(const charT* str)

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_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/string_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<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:85:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const charT*, boost::basic_string_view<charT, traits>::size_type) [with charT = char; traits = std::char_traits<char>; boost::basic_string_view<charT, traits>::size_type = long unsigned int]

       BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:85:23: note:   candidate expects 2 arguments, 1 provided

/usr/local/include/boost/utility/string_view.hpp:78:9: note: candidate: template<class Allocator> boost::basic_string_view<charT, traits>::basic_string_view(const std::__cxx11::basic_string<charT, traits, Allocator>&)

         basic_string_view(const std::basic_string<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<char>, Allocator>' and 'const char'

     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:68:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view(const boost::basic_string_view<charT, traits>&) [with charT = char; traits = std::char_traits<char>]

       BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:68:23: note:   no known conversion for argument 1 from 'const char' to 'const boost::basic_string_view<char, std::char_traits<char> >&'

/usr/local/include/boost/utility/string_view.hpp:65:23: note: candidate: constexpr boost::basic_string_view<charT, traits>::basic_string_view() [with charT = char; traits = std::char_traits<char>]

       BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT

                       ^~~~~~~~~~~~~~~~~

/usr/local/include/boost/utility/string_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<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = const char*; _OI = boost::basic_string_view<char, std::char_traits<char> >*]':

/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_string_view<char, std::char_traits<char> >*]'

/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<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >]'

/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<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >]'

/usr/local/include/c++/6.1.0/bits/vector.tcc:637:16:   required from 'void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = boost::basic_string_view<char, std::char_traits<char> >*]'

/usr/local/include/c++/6.1.0/bits/stl_vector.h:1375:4:   required from 'void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = const char*; _Tp = boost::basic_string_view<char, std::char_traits<char> >; _Alloc = std::allocator<boost::basic_string_view<char, std::char_traits<char> > >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<boost::basic_string_view<char, std::char_traits<char> >*, std::vector<boost::basic_string_view<char, std::char_traits<char> > > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = boost::basic_string_view<char, std::char_traits<char> >*]'

/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<L, R>, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Iterator = const char*; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; Left = boost::spirit::x3::raw_directive<boost::spirit::x3::plus<boost::spirit::x3::negated_char_parser<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, char> > > >; Right = boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>; 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<L, R>, 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/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&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >; Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/operator/kleene.hpp:32:48:   required from 'bool boost::spirit::x3::kleene<Subject>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = const char*; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >; 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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:35:68:   required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

/usr/local/include/boost/spirit/home/x3/core/parse.hpp:60:26:   required from 'bool boost::spirit::x3::parse(const Iterator&, Iterator, const Parser&, Attribute&) [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::char_encoding::standard, char> > > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Attribute = std::vector<boost::basic_string_view<char, std::char_traits<char> > >]'

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_string_view<char, std::char_traits<char> >' and 'const char')

        *__result = *__first;

        ~~~~~~~~~~^~~~~~~~~~

In file included from main.cpp:4:0:

/usr/local/include/boost/utility/string_view.hpp:71:26: note: candidate: boost::basic_string_view<charT, traits>& boost::basic_string_view<charT, traits>::operator=(const boost::basic_string_view<charT, traits>&) [with charT = char; traits = std::char_traits<char>]

       basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT {

                          ^~~~~~~~

/usr/local/include/boost/utility/string_view.hpp:71:26: note:   no known conversion for argument 1 from 'const char' to 'const boost::basic_string_view<char, std::char_traits<char> >&'

live example

What am I missing here?

解决方案

By overloading/specializing move_to you are basically telling X3 how to convert from a boost::iterator_range (actually just a pair of iterators) to boost::string_view. Unfortunately it doesn't know that both are "equivalent" (one is a substitute of the other seems to be the nomenclature used in Spirit). And so your original example works because you are explicitly requesting the transformation from iterators to string_view but this one fails since X3 lacks the required information to infer the appropriate attribute type.

Especifically the problem seems to be here, where it is tested whether the attribute of the parser (in this case raw_attribute_type) is compatible with the value_type of the expected attribute (boost::string_view). This test fails and then a code path where the attribute is not "passed as is" is chosen causing the error you get.

With all this in mind there seem to be two possible approaches: either explicitly request the transformation or provide Spirit with the information about the compatibility of the attributes.

Missing some of the helpers we had in Qi (attr_cast, as[]) it seems that the way to force an attribute transformation in X3 is by creating an extra rule with the actual type you want:

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

You could also (especially if you need to do this in several rules) use an approach I've seen sehe use several times (like here) that creates a variable template lambda that can be used like as<T>(parser) that hides the creation of that extra rule and forces the attribute of parser to transform into T.

template<typename T>
auto as = [](auto p) { return rule<struct _, T>{} = as_parser(p); };
auto const str_vec = *as<boost::string_view>(x3::raw[ +~char_('_')] >> '_');

The way to provide Spirit with the information about the compatibility of the attributes seems to be to specialize x3::traits::is_substitute:

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

But as you mentioned in the comments this doesn't seem to be a documented customization point and so I'm not sure if it's a good idea to use it. Ideally this would be specialized by default in X3, but as sehe commented in the previous question, the fact that the storage referred by the iterators must be contiguous complicates the situation.

这篇关于解析为vector&lt; boost :: string_view&gt;使用boost :: spirit :: x3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆