In my my previous question it was suggested that the performance of my boost::spirit::x3
parser could be improved by parsing into a boost::string_view
using the raw
directive.
However, I have difficulties getting it to compile. This is what I found out:
Before
x3
, one had to specializeassign_to_attribute_from_iterators
(see e.g. this SO answer) to handle theraw
directive.x3
now uses themove_to
free function instead (see e.g. this SO answer).
I therefore added a move_to
overload which works if I parse from char*
:
#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 = raw[ +~char_('_')] >> '_';
}
int main()
{
std::string input = "hello world_";
boost::string_view str;
parse(input.data(), input.data()+input.size(), parser::str, str);
std::cout << str;
}
However, it does not compile:
1) If I parse using std::string::const_iterator
parse(input.cbegin(), input.cend(), parser::str, str);
The constructor of boost::string_view
either expects a const char*
or a std::string&
.
main.cpp:12:16: error: no matching function for call to 'boost::basic_string_view<char, std::char_traits<char> >::basic_string_view(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, std::size_t)'
v = boost::string_view(b, std::size_t(std::distance(b,e)));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
How can I instantiate a boost::string_view
from std::string::const_iterator
?
2) If boost/spirit/home/x3.hpp
is included prior to the move_to
overload
Why is my overload not chosen? Isn't it a better overload than any of those defined in boost/spirit/home/x3/support/traits/move_to.hpp
?
How can I make sure my overload is chosen regardless the order of inclusion?
I'd simply write what you want:
v = boost::string_view(&*b, std::distance(b,e));
You might want to check that storage is contiguous¹ as a concept check for your input range. In that respect, it might be clearer to also require the iterator to be random-access, and write:
v = boost::string_view(&*b, e-b);
¹ this is a requirement for string_view anyways
来源:https://stackoverflow.com/questions/39225502/parsing-from-stdstring-into-a-booststring-view-using-boostspiritx3