Re: [Spirit Devel] [ADAPT_ADT and Karma] ADAPT_ADT causes grammars with variants to not compile in karma

"Hartmut Kaiser" <[email protected]> Sat, 20 Nov 2010 09:03:51 -0600
Newsgroups gmane.comp.parsers.spirit.devel
Message-ID <[email protected]>
> I am trying to output a variant in using the ADAPT_ADT macro and
> Karma.  It seems to be a problem with the adt_proxy class that causes the
> variant conversion to fail.  I can easily get similar code working with
> ADAPT_STRUCT.
> The following fails to compile.
> 
> typedef const boost::variant<std::string,unsigned int> const_variant_type;
> 
> struct y
> {
>   const_variant_type& get() const;
>   void set(const_variant_type&);
> };
> 
> BOOST_FUSION_ADAPT_ADT(y,(const_variant_type,const_variant_type,obj.get(),
> obj.set(val)))
> 
> int main()
> {
>   using namespace boost::spirit::karma;
>   using namespace boost::phoenix;
>   boost::spirit::karma::rule<std::string::iterator,std::string()> a;
>   boost::spirit::karma::rule<std::string::iterator,unsigned int()> b;
>   boost::spirit::karma::rule<std::string::iterator,y()> Y;
>   Y = (a | b)[_1 = at_c<0>(_val)];
> }

Yep, that won't work. Adaptation of ADT's is implemented by creating a proxy
type, which encapsulates your actual attribute. This proxy type is not
convertible to the lhs (the variant) by default (how could it?). For this
reason, the assignment fails.

OTOH, the built-in Spirit attribute propagation rules 'know' about this
proxy type (because you included
boost/spirit/home/support/adapt_adt_attributes.hpp). That means if you rely
on those it will work:

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/home/support/adapt_adt_attributes.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant.hpp>

typedef const boost::variant<std::string,unsigned int> const_variant_type;

struct y
{
  const_variant_type& get() const;
  void set(const_variant_type&); 
};

BOOST_FUSION_ADAPT_ADT(y,(const_variant_type,const_variant_type,obj.get(),ob
j.set(val)))

int main()
{
  namespace karma = boost::spirit::karma;
  namespace phoenix = boost::phoenix;
  karma::rule<std::string::iterator,std::string()> a;
  karma::rule<std::string::iterator,unsigned int()> b;
  karma::rule<std::string::iterator,y()> Y;
  Y = (a | b) << karma::eps;
}

By converting your rhs of 'Y' into a (artificial) sequence, Spirit will
automatically apply the default attribute propagation rules for that
sequence, allowing the code to compile just fine.

Regards Hartmut
---------------
http://boost-spirit.com




------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev