3

I'm updating some old code which worked under older (~1.38 or so) versions of boost. I've updated to boost 1.63 and can not seem to figure out how to get the old version to compile.

This is 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 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 get and error message along the lines of

invalid initialization of type const StateStruct::StateStruct& from expression of type boost::fusion::vector<boost::fusion::vector<char, std::vector<char, std::allocator<char> > >, float>

without the semantic action the code compiles and debugging the state rule shows the expected results. What do I need to do to correctly initialize the struct?

Jonas
  • 6,915
  • 8
  • 35
  • 53

1 Answers1

2

I agree this looks like a regression, you may want to report it to the maintainers at the [spirit-general] mailing list.

On a hunch I remembered an obscure define that got introduced as some kind of a compatibility hack¹. Lo and behold, the thing compiles with BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT defined:

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 got introduced to give some people a feature that could not be generally enabled because it would break existing code)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Sir you have saved me untold frustration. Do you happen to remember where this is/was documented because I drew a blank from several days of searching. As a note I apologize for not posting a full program. The machine I'm working on is not able to connect to the internet. – Gary Sanders May 08 '17 at 11:31
  • I just remembered this rare thing on the mailing list. It's from 2011 http://boost.2283326.n4.nabble.com/fusion-vector2-std-pair-compatibility-td3529649i20.html. – sehe May 08 '17 at 11:35
  • Just googling it again, turns out the docs make a mention of it as well http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/what_s_new/spirit_2_5.html#spirit.what_s_new.spirit_2_5.making_stuff_work. Also, see this 2016 answer http://stackoverflow.com/a/40726982/85371 for other approaches – sehe May 08 '17 at 11:35
  • This mention from 2012 makes the interesting observation that [_"BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is cool, but not defining it is sometimes even cooler. Because it allows the rule's attributes to be different from the attributes synthesized by the parser"_](https://sourceforge.net/p/spirit/mailman/message/29627088/) – sehe May 08 '17 at 11:38
  • Thanks, I'll read the references you posted. I'm guessing I never tried this past about 1_42 as we're saddled with RHEL 6 where I work. – Gary Sanders May 08 '17 at 14:47