所以我要做的是解析一个字符串列表:
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
没有任何问题,所以我不相信这是一个错误。我错过了什么吗?
答案 0 :(得分:2)
我认为这是a Spirit bug。如果你查看ticket的底部,你会找到一个我认为可以修复它的补丁。
答案 1 :(得分:1)
有一个例子here也不起作用。使用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
]
快速谷歌搜索&#34; iterator_adaptor dereference temporary&#34;导致this建议Reference
iterator_adaptor
参数为非引用类型。
为了实现这一目标,您需要更改文件&#34; boost / spirit / home / classic / iterator / impl / position_iterator.ipp&#34;。具体而言,您需要更改:
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更改为:
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;
}