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

时间:2016-08-30 10:50:07

标签: c++ boost boost-spirit-x3 string-view

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

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

  • x3之前,必须专门设置assign_to_attribute_from_iterators(请参阅例如this SO answer)来处理raw指令。

  • x3现在使用move_to免费功能(请参阅例如this SO answer)。

因此我添加了一个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

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

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

live example

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

1 个答案:

答案 0 :(得分:2)

我只是写下你想要的东西:

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

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

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

¹这是string_view的要求