boost :: spirit :: position_iterator2出现奇怪的错误 [英] strange error with boost::spirit::position_iterator2

查看:68
本文介绍了boost :: spirit :: position_iterator2出现奇怪的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想做的是解析一个字符串列表:

  namespace qi = boost :: spirit :: qi;名称空间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最后;pos_iterator pfirst(first,last,std :: string("DD"));pos_iterator plast;使用qi :: lexeme;使用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 没问题,所以我不认为这是一个错误.我想念什么吗?

解决方案

有一个示例

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

收件人:

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

这会导致g ++和vc11中出现新错误:

  boost_1_52_0 \ boost/concept_check.hpp(212):错误C2440:正在初始化":无法从"boost :: detail :: iterator_category_with_traversal<类别,遍历<到"std :: forward_iterator_tag"和[Category = std :: input_iterator_tag,Traversal = boost :: forward_traversal_tag]没有构造函数可以采用源类型,或者构造函数重载解析度不明确 

如果将 iterator_adaptor typedef更改为:

,可以避免这种情况

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

这可以使下面的程序(基于您的代码)和boost-spirit.com的示例都能正常工作,但是我不确定在其他情况下该程序是否不会中断,因此请自行决定使用它./p>

  #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>命名空间qi = boost :: spirit :: qi;名称空间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最后;pos_iterator pfirst(first,last,std :: string("DD"));pos_iterator plast;使用qi :: lexeme;使用ascii :: alpha;std :: vector< std :: string>DDD;bool res = qi :: phrase_parse(pfirst,plast,* lexeme [+ alpha,ascii :: space,DDD);if(res& pfirst == plast){对于(const auto& d:DDD)std :: cout<<d<<("<< d.size()<<)"<<std :: endl;}别的{std :: cout<<解析错误."<<std :: endl;}返回0;} 

So what I am trying to do is to parse a list of strings:

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;

What i get in DDD are 3 strings of the correct size, but all of whitespaces.

If instead i use

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

everything works as expected. I used position_iterator2 in the past without any problem, so I don't believe it is a bug. Am I missing something?

解决方案

There is an example here that doesn't work either. Using Visual Studio 2012 both give a warning:

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
         ]

A quick google search of "iterator_adaptor dereference temporary" leads to this that recommends that the Reference parameter of iterator_adaptor be a non-reference type.

In order to accomplish that you need to change the file "boost/spirit/home/classic/iterator/impl/position_iterator.ipp". Specifically you'd need to change:

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

to:

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

this leads to a new error in both g++ and 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

That can be avoided if you change the iterator_adaptor typedef to:

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

This makes both the program below (based on your code) and the example from boost-spirit.com work, but I'm not sure that it won't break in other cases, so use it at your discretion.

#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;
}

这篇关于boost :: spirit :: position_iterator2出现奇怪的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆