парсинг из std::string в boost::string_view с помощью boost::spirit::x3

В моем моем предыдущем вопросе было высказано предположение, что производительность моего синтаксического анализатора boost::spirit::x3 можно улучшить, разобрав его в boost::string_view с помощью директивы raw.

Однако у меня возникают трудности с его компиляцией. Вот что я узнал:

  • До x3 нужно было специализировать assign_to_attribute_from_iterators (см., например, этот ответ SO) для обработки директивы raw.

  • x3 теперь вместо этого использует функцию move_to free (см., например, этот ответ SO).

Поэтому я добавил перегрузку 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;
}

живой пример

Однако он не компилируется:

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

живой пример

Как я могу создать экземпляр boost::string_view из std::string::const_iterator?

2) Если boost/spirit/home/x3.hpp включено до перегрузки move_to

живой пример

Почему моя перегрузка не выбрана? Разве это не лучшая перегрузка, чем любая из тех, что определены в boost/spirit/home/x3/support/traits/move_to.hpp? Как я могу убедиться, что моя перегрузка выбрана независимо от порядка включения?


person m.s.    schedule 30.08.2016    source источник
comment
2) частичное упорядочение. Я не думаю, что есть способ обойти это (я не нашел его раньше) - см. en.cppreference.com/w/cpp/language/   -  person sehe    schedule 30.08.2016
comment
@sehe Я думаю, было бы лучше, если бы directive/raw.hpp было изменено на это: см. здесь @строка 42-44, тогда можно было бы использовать ADL, а перегрузка находилась бы в namespace boost   -  person m.s.    schedule 30.08.2016


Ответы (1)


Я бы просто написал то, что вы хотите:

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

Возможно, вы захотите проверить непрерывность хранилища¹ в качестве проверки концепции для вашего диапазона ввода. В этом отношении может быть понятнее также потребовать, чтобы итератор был с произвольным доступом, и написать:

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

¹ в любом случае это требование для string_view

person sehe    schedule 30.08.2016
comment
можно ли проверить концепцию через Boost Concept Checking? - person m.s.; 30.08.2016
comment
Не понимаю, почему бы и нет, хотя я им не пользовался. - person sehe; 30.08.2016