странная ошибка с boost :: spirit :: position_iterator2

Итак, я пытаюсь разобрать список строк:

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

std::string TEST = "aa\nbbbb\nccc\n";

std::istringstream INPUT (TEST);
std::noskipws(INPUT);

typedef std::istreambuf_iterator<char> base_iterator;
typedef boost::spirit::multi_pass<base_iterator>  multi_pass_iter;
typedef boost::spirit::classic::position_iterator2<multi_pass_iter> pos_iterator;

base_iterator base_begin(INPUT);

multi_pass_iter first =  boost::spirit::make_default_multi_pass(base_begin);
multi_pass_iter last;

pos_iterator pfirst(first,last,std::string("DD"));
pos_iterator plast;

using qi::lexeme;
using ascii::alpha;

std::vector<std::string> DDD;
bool res = qi::phrase_parse(pfirst,plast,* lexeme[+alpha],ascii::space,DDD);

for (const auto & d : DDD) std::cout << d << " (" << d.size() << ")" << std::endl;

Что я получаю в DDD 3 строки правильного размера, но все пробелы.

Если вместо этого я использую

bool res = qi::phrase_parse(first,last,* lexeme[+alpha],ascii::space,DDD);

все работает как положено.
я использовал position_iterator2 в прошлом без проблем, поэтому я не верю, что это ошибка. Я что-то пропустил?

2

Решение

Есть пример Вот это тоже не работает. При использовании Visual Studio 2012 оба выдают предупреждение:

boost/iterator/iterator_adaptor.hpp(306): warning C4172: returning address of local variable or temporary
boost_1_52_0\boost/iterator/iterator_adaptor.hpp(306) : while compiling class template member function 'const char &boost::iterator_adaptor<Derived,Base,Value,Traversal>::dereference(void) const'
with
[
Derived=boost::spirit::classic::position_iterator2<forward_iterator_type>,
Base=forward_iterator_type,
Value=const char,
Traversal=boost::forward_traversal_tag
]

Быстрый поиск в Google по запросу «iterator_adaptor разыменование временно» приводит к этот который рекомендует, чтобы Reference параметр iterator_adaptor быть не ссылочным типом.

Для этого вам нужно изменить файл «boost / spirit / home / classic / iterator / impl / position_iterator.ipp». В частности, вам нужно изменить:

typedef boost::iterator_adaptor<
main_iter_t,
ForwardIterT,
const_value_type,
boost::forward_traversal_tag
> type;

чтобы:

typedef boost::iterator_adaptor<
main_iter_t,
ForwardIterT,
const_value_type,
boost::forward_traversal_tag,
const_value_type
> type;

это приводит к новой ошибке в g ++ и vc11:

boost_1_52_0\boost/concept_check.hpp(212): error C2440: 'initializing' : cannot convert from 'boost::detail::iterator_category_with_traversal<Category,Traversal>' to 'std::forward_iterator_tag'
with
[
Category=std::input_iterator_tag,
Traversal=boost::forward_traversal_tag
]
No constructor could take the source type, or constructor overload resolution was ambiguous

Этого можно избежать, если вы измените iterator_adaptor typedef to:

typedef boost::iterator_adaptor<
main_iter_t,
ForwardIterT,
const_value_type,
std::forward_iterator_tag,
const_value_type
> type;

Это позволяет работать как приведенной ниже программе (на основе вашего кода), так и примеру на boost-spirit.com, но я не уверен, что она не сломается в других случаях, поэтому используйте ее по своему усмотрению.

#include <vector>
#include <istream>
#include <sstream>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

int main()
{

std::string TEST = "aa\nbbbb\nccc\n";

std::istringstream INPUT (TEST);
std::noskipws(INPUT);

typedef std::istreambuf_iterator<char> base_iterator;
typedef boost::spirit::multi_pass<base_iterator>  multi_pass_iter;
typedef boost::spirit::classic::position_iterator2<multi_pass_iter> pos_iterator;

base_iterator base_begin(INPUT);

multi_pass_iter first =  boost::spirit::make_default_multi_pass(base_begin);
multi_pass_iter last;

pos_iterator pfirst(first,last,std::string("DD"));
pos_iterator plast;

using qi::lexeme;
using ascii::alpha;

std::vector<std::string> DDD;
bool res = qi::phrase_parse(pfirst,plast,* lexeme[+alpha],ascii::space,DDD);

if(res && pfirst==plast)
{
for (const auto & d : DDD)
std::cout << d << " (" << d.size() << ")" << std::endl;
}
else
{
std::cout << "Parsing error." << std::endl;
}

return 0;
}
1

Другие решения

Я думаю это Духовный жук. Если вы посмотрите на нижнюю часть билет вы найдете патч, который, я думаю, исправит это.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector