Search code examples
c++boostboost-spiritboost-spirit-qiboost-spirit-x3

spirit x3 cannot propagate attributes of type optional<vector>


A simple parser as on Coliru. The parser -(+x3::alpha) should be able to propagate an attribute of type boost::optional<std::string> as Qi does. But it does not compile.

std::string const input = "abc";
boost::optional<std::string> attr;
if(x3::parse(boost::begin(input),boost::end(input),
    -(+x3::alpha),
    attr)) {
    std::cout<<"match!"<<std::endl;
}
else {
    std::cout<<"NOT match!"<<std::endl;
}

Solution

  • I don't think the normative claim "should be able [...] as Qi does" cuts wood. X3 is not an evolution of Qi, for very good reasons (such as this).

    An oft recurring pattern is that type hints are required in more complicated propagation scenarios. The ugly verbose way could be like this:

        -(x3::rule<struct _, std::string> {} = +x3::alpha),
    

    Live On Coliru

    Or you can use the hack I described previously:

    namespace {
        template <typename T>
        struct as_type {
            template <typename Expr>
                auto operator[](Expr&& expr) const {
                    return x3::rule<struct _, T>{"as"} = x3::as_parser(std::forward<Expr>(expr));
                }
        };
    
        template <typename T> static const as_type<T> as = {};
    }
    

    Live On Coliru