Passing the spirit of a parsed structure to a function using phoenix :: bind

I am updating old code that worked under older versions of boost (~ 1.38 or so). I updated to increase 1.63 and can't seem to figure out how to get the old version to compile.

These are the relevant parts

void print (StateStruct const& ss)
{
   std::cout << ss.Name;
}

struct StateStruct
{
  std::string Name;
  float avalue;
}

BOOST_FUSION_ADAPT_STRUCT (
  StateStruct,
  (std::string, NAME)
  (float, avalue)
)

      

and the parser rule that was used to work

state %=
( qi::lexeme[qi::char_(a-zA-Z) >> +qi::char("-a-zA-Z0-9_")]
 >> qi::float_
)
[phoenix::bind(&print, qi::_val)]
;

qi::rule (Iterator, StateStruct(), skipper_type) state;

      

With g ++ 6.3.0 and boost 1.63 I am getting an error along the lines

invalid type initialization const StateStruct::StateStruct&

from type expressionboost::fusion::vector<boost::fusion::vector<char, std::vector<char, std::allocator<char> > >, float>

without semantic action, the code compiles and debugs a state rule that shows the expected results. What do I need to do to initialize the structure correctly?

+3


source to share


1 answer


I agree that this looks like a regression, you can report it to the maintainers on the [spirit-general] mailing list.

In anticipation, I remembered an obscure definition that emerged as a kind of hackยน compatibility. Lo and lo and behold, the thing is compiled with BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT

:

Live On Coliru:

#define BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

struct StateStruct { std::string Name; float avalue; };

BOOST_FUSION_ADAPT_STRUCT(StateStruct, Name, avalue)

void print(StateStruct const& ss) { std::cout << "print: " << ss.Name << "\n"; }

namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;

int main() {
    using Iterator = std::string::const_iterator;
    using skipper_type = qi::space_type;
    qi::rule<Iterator, StateStruct(), skipper_type> state;

    state %=
        ( qi::as_string [ qi::lexeme[qi::char_("a-zA-Z") >> +qi::char_("-a-zA-Z0-9_")] ] >> qi::float_
        )
        [ px::bind(&print, qi::_val) ]
        ;

    std::string const input("identifier31415 3.1415");
    Iterator f = input.begin(), l = input.end();
    StateStruct parsed;
    bool ok = qi::phrase_parse(f, l, state, qi::space, parsed);

    if (ok)
        std::cout << "Parsed: " << boost::fusion::as_vector(parsed) << "\n";
    else
        std::cout << "Parse failed\n";

    if (f != l)
        std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}

      



Printing

print: identifier31415
Parsed: (identifier31415 3.1415)

      

ยน (I think it came up to give some people a feature that cannot be enabled at all because it will break existing code)

+2


source







All Articles