Search code examples
constructorattributesboost-spiritboost-spirit-qi

With Boost.spirit, is there any way to pass additional argument to attribute constructor?


Maybe a noob question, I've a piece of code like this:

struct S {
    S() {...}
    S(int v) {
        // ...
    }
};
qi::rule<const char*, S(), boost::spirit::ascii::space_type> ip=qi::int_parser<S()>();
qi::rule<const char*, std::vector<S>(), boost::spirit::ascii::space_type> parser %= ip % ',';
...

Rules above can work, but the code breaks if S constructors require additional parameters, such as:

struct S {
    S(T t) {...}
    S(T t, int v) {
        // ...
    }
};

I've spent days to find solution, but no luck so far. Can anyone help?


Solution

  • There is no direct way, but you can probably explicitely initialize things:

    qi::rule<It, optional<S>(), Skipper> myrule;
    
    myrule %= 
           qi::eps [ _val = phoenix::construct<S>(42) ] >>
           int_parser<S()>;
    

    However, since you are returning it from the int_parser, my intuition says that default-initialization should be appropriate (or perhaps the type S doesn't have a single, clear, responsibility?).

    Edit

    In response to the comment, it looks like you want this:

    T someTvalue;    
    
    myrule = qi::int_ 
       [ qi::_val = phx::construct<S>(someTvalue, qi::_1) ];
    

    Or, if someTvalue is a variable outside the grammar constructor, and may change value during execution of the parser (and it lives long enough!), you could do

    myrule = qi::int_ 
       [ qi::_val = phx::construct<S>(phx::ref(someTvalue), qi::_1) ];
    

    Hope that helps