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?
source to share
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
:
#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)
source to share