c++ - Error when adapting a class with BOOST_FUSION_ADAPT_ADT -
i've following class:
#ifndef wfractal_fractal_metadata_h_ #define wfractal_fractal_metadata_h_ #include <string> namespace wfractal { namespace fractal { class metadata { public: void setauthorname(const std::string &name); void setauthoremail(const std::string &email); void setbriefdescription(const std::string &brief); void setcompletedescription(const std::string &description); std::string getauthorname() const; std::string getauthoremail() const; std::string getbriefdescription() const; std::string getcompletedescription() const; public: bool operator==(const metadata &other); private: std::string m_name; std::string m_email; std::string m_brief; std::string m_description; }; } // namespace fractal } // namespace wfractal #endif // !wfractal_fractal_metadata_h_
i want parse using boost::spirit
following file content:
metadata { author = "me"; email = "myemail"; brief = "brief description"; description = "complete description"; }
i've read this page can use boost_fusion_adapt_struct
in order parse it. grammar template:
#ifndef wfractal_fractal_parser_metadatagrammar_h_ #define wfractal_fractal_parser_metadatagrammar_h_ #include <boost/fusion/adapted/adt/adapt_adt.hpp> #include <boost/fusion/include/adapt_adt.hpp> #include <boost/spirit/include/qi_no_case.hpp> #include <string> #include "fractal/metadata.h" boost_fusion_adapt_adt( wfractal::fractal::metadata, (obj.getauthorname(), obj.setauthorname(val)) (obj.getauthoremail(), obj.setbriefdescription(val)) (obj.getbriefdescription(), obj.setcompletedescription(val)) (obj.getcompletedescription(), obj.setauthoremail(val)) ) namespace wfractal { namespace fractal { namespace parser { template <typename iterator> struct metadataparser : boost::spirit::qi::grammar<iterator, metadata(), boost::spirit::ascii::space_type> { metadataparser() : metadataparser::base_type(start) { using boost::spirit::qi::int_; using boost::spirit::qi::lit; using boost::spirit::qi::double_; using boost::spirit::qi::lexeme; using boost::spirit::ascii::char_; using boost::spirit::ascii::no_case; quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= no_case[lit("metadata")] >> '{' >> no_case[lit("author")] >> '=' >> quoted_string >> ';' >> no_case[lit("email")] >> '=' >> quoted_string >> ';' >> no_case[lit("brief")] >> '=' >> quoted_string >> ';' >> no_case[lit("description")] >> '=' >> quoted_string >> ';' >> '}' ; } boost::spirit::qi::rule<iterator, std::string(), boost::spirit::ascii::space_type> quoted_string; boost::spirit::qi::rule<iterator, metadata(), boost::spirit::ascii::space_type> start; }; } // namespace parser } // namespace fractal } // namespace wfractal #endif // !wfractal_fractal_parser_metadatagrammar_h_
when create instance of grammar (always following page example), obtain compiler error:
typedef string::const_iterator stringiterator; typedef parser::metadataparser<stringiterator> metadataparser; metadataparser parser;
i obtain lot of errors (typical of boost...) , i've noticed inside them many copy of error:
src/fractal/filefactory.cpp:27:17: required here /usr/include/boost/spirit/home/qi/detail/assign_to.hpp:152:18: error: no matching function call ‘boost::fusion::extension::adt_attribute_proxy<wfractal::fractal::metadata, 0, false>::adt_attribute_proxy(const std::__cxx11::basic_string<char>&)’ attr = static_cast<attribute>(val);
what i'm doing wrong? how can fix it?
edit
as suggested m.s. i've added #include <boost/spirit/include/support_adapt_adt_attributes.hpp>
header not working.
#ifndef wfractal_fractal_parser_metadataparser_h_ #define wfractal_fractal_parser_metadataparser_h_ #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_object.hpp> #include <boost/fusion/include/io.hpp> #include <boost/fusion/adapted/adt/adapt_adt.hpp> #include <boost/fusion/include/adapt_adt.hpp> #include <boost/spirit/include/support_adapt_adt_attributes.hpp> #include <string> #include "fractal/metadata.h" boost_fusion_adapt_adt( wfractal::fractal::metadata, (obj.getauthorname(), obj.setauthorname(val)) (obj.getauthoremail(), obj.setauthoremail(val)) (obj.getbriefdescription(), obj.setbriefdescription(val)) (obj.getcompletedescription(), obj.setcompletedescription(val)) ) namespace wfractal { namespace fractal { namespace parser { template <typename iterator> struct metadataparser : boost::spirit::qi::grammar<iterator, metadata(), boost::spirit::ascii::space_type> { metadataparser() : metadataparser::base_type(start) { using boost::spirit::qi::lit; using boost::spirit::qi::lexeme; using boost::spirit::ascii::char_; using boost::spirit::ascii::no_case; quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= no_case[lit("metadata")] >> '{' >> ((no_case[lit("author")] >> '=' >> quoted_string >> ';') ^ (no_case[lit("email")] >> '=' >> quoted_string >> ';') ^ (no_case[lit("brief")] >> '=' >> quoted_string >> ';') ^ (no_case[lit("description")] >> '=' >> quoted_string >> ';')) >> '}' ; } boost::spirit::qi::rule<iterator, std::string(), boost::spirit::ascii::space_type> quoted_string; boost::spirit::qi::rule<iterator, metadata(), boost::spirit::ascii::space_type> start; }; } // namespace parser } // namespace fractal } // namespace wfractal #endif // !wfractal_fractal_parser_metadataparser_h_
hmm.
after long struggle modular boost , git... i've found regression.
the regression has been partially fixed pull request:
sadly, it's still broken in presence of permutation parser. i've tested boost_fusion_adapt_struct
verify not broken in other way.
i'll add reduced sample pr comments. meanwhile, here's reproducer made selfcontained:
#include <boost/spirit/include/qi.hpp> #include <boost/fusion/adapted.hpp> #include <iostream> class foo { public: char const& geta() const { return a; } char const& getb() const { return b; } void seta(char value) { = value; } void setb(char value) { b = value; } private: char a, b; }; boost_fusion_adapt_adt( foo, (char const&, char const&, obj.geta(), obj.seta(val)) (char const&, char const&, obj.getb(), obj.setb(val)) ) int main() { namespace qi = boost::spirit::qi; boost::spirit::istream_iterator f(std::cin), l; // input e.g. "a=a;b=b;" foo foo; bool r = qi::parse(f, l, #if 0 // fails compile ("a=" >> qi::char_ >> ';') ^ ("b=" >> qi::char_ >> ';') #else // compiles fix pr #153 ("a=" >> qi::char_ >> ';') >> ("b=" >> qi::char_ >> ';') #endif , foo); if (r) std::cout << "parsed: " << boost::fusion::as_vector(foo) << "\n"; else std::cerr << "parse failed\n"; }
if you, however, change #if 1
#if 0
, output:
parsed: (a b)
note of course that's assuming use branch has pr 153 applied.
Comments
Post a Comment