spirit x3 规则无法在序列解析器中合成 boost::iterator_range 类型的属性

spirit x3 rule cannot synthesize attribute of type boost::iterator_range in a sequence parser

在简单的解析器测试中 Live On Coliru

std::string str("x123x");
boost::iterator_range<boost::range_iterator<decltype(str)>::type> attr;
if( x3::parse( boost::begin(str), boost::end(str), x3::lit('x') >> x3::raw[+x3::digit] >> x3::lit('x'), attr ) ) {
    std::cout<<"Match! attr = "<<attr<<std::endl;
} else {
    std::cout<<"Not match!"<<std::endl;
}

解析器

x3::lit('x') >> x3::raw[+x3::digit] >> x3::lit('x')

应该合成 boost::iterator_range<Iterator> 类型的属性。但它无法编译。如果我们删除两个 x3::lit('x') 中的任何一个,它就会编译。尽管 Live on Coliru,但相同的代码可以使用 qi 进行编译。

有意思。实际上它确实编译:

Live On Coliru

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

namespace x3 = boost::spirit::x3;

int main() {
    std::string const str("x123x");
    boost::iterator_range<std::string::const_iterator> attr;
    if(x3::parse(boost::begin(str), boost::end(str), x3::raw[+x3::digit], attr)) {
        std::cout<<"Match! attr = "<<attr<<std::endl;
    } else {
        std::cout<<"Not match!"<<std::endl;
    }
}

让它崩溃的是周围的环境:

// simple (ok):
x3::parse(boost::begin(str), boost::end(str), x3::raw[+x3::digit], attr);
// ok:
parse(boost::begin(str), boost::end(str), x3::eps >> x3::raw[+x3::digit], attr);
parse(boost::begin(str), boost::end(str), x3::raw[+x3::digit] >> x3::eps, attr);
// breaks:
parse(boost::begin(str), boost::end(str), x3::eps >> x3::raw[+x3::digit] >> x3::eps, attr);

我的猜测是元编程在这种情况下错误地将 iterator_range 视为融合序列。我当然认为这是一个错误。

你应该向上游报告。

遗憾的是我还没有找到 "homeopathic" 解决方法。