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

问题描述

在我的中,建议我的 boost :: spirit :: x3 解析器的性能可以通过解析为 boost :: string_view 使用 raw 指令。



但是,我无法编译。
这是我发现的:




  • 之前 x3 ,则必须专门处理 assign_to_attribute_from_iterators (请参阅 )来处理 raw 指令。


  • x3 现在使用 move_to 功能(参见例如)。




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

}}}

} //命名空间boost

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

命名空间解析器
{
命名空间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;
}



但是,不会 compile:



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

  parse(input.cbegin(),input.cend(),parser :: str,str); 

需要一个 const char * std :: string&

 c> main.cpp:12:16:error:没有匹配的函数调用'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)));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 〜



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



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





为什么不选择我的重载?这不是比?
如何确定我的重载是否被选择,而不考虑包含的顺序?

解决方案

你想要:

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

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

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






p>

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 specialize assign_to_attribute_from_iterators (see e.g. this SO answer) to handle the raw directive.

  • x3 now uses the move_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;
}

live example

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)));
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

live example

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

live example

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

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

08-21 19:47