使用 boost::spirit::x3 从 std::string 解析为 boost::string_view

parsing from std::string into a boost::string_view using boost::spirit::x3

在我的 my previous question 中,有人建议我的 boost::spirit::x3 解析器的性能可以通过使用 raw 指令解析为 boost::string_view 来提高。

但是,我很难编译它。 这是我发现的:

因此,我添加了一个 move_to 重载,如果我从 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;
}

live example

但是,编译:

1) 如果我使用 std::string::const_iterator

进行解析
parse(input.cbegin(), input.cend(), parser::str, str);

boost::string_view 的构造函数需要 const char*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)));
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

live example

如何从 std::string::const_iterator 实例化 boost::string_view

2) 如果 boost/spirit/home/x3.hppmove_to 重载之前包含

live example

为什么我的重载没有被选中?它不是比 boost/spirit/home/x3/support/traits/move_to.hpp 中定义的任何重载更好吗? 无论包含的顺序如何,我如何确保选择了我的重载?

你想写什么我就写什么:

v = boost::string_view(&*b, std::distance(b,e));

您可能想检查存储是否连续¹,作为输入范围的概念检查。在这方面,还要求迭代器是随机访问的可能会更清楚,并写成:

v = boost::string_view(&*b, e-b);

¹ 无论如何,这是 string_view 的要求