Le 05/03/2011 13:36, MM a écrit :
>> -----Original Message-----
>> From: Gevorg Voskanyan [mailto:v_gevorg@...]
>> Sent: 05 March 2011 12:06
>> To: Spirit General Mailing List
>> Subject: Re: [Spirit-general] nabialek-trick and production rules having
>> attributes that all derive from the same struct
>>
>>> Joel de Guzman wrote:
>>>
>>> There is now fusion::copy in the trunk:
>>>
>>> boost/fusion/algorithm/auxiliary/copy.hpp
>>>
>>> or
>>>
>>> boost/fusion/include/copy.hpp
>>>
>>> The syntax is:
>>>
>>> copy(src, dest)
>>>
>>> Regards,
>>> --
>>> Joel de Guzman
>>
>> Great, thanks Joel!
>>
>> MM wrote:
>>> so with copy available in fusion trunk, there would need to be a
> newDerived
>>> functor for each different derived type,
>>> because each derived type has a different number of members, some have
> 5
>>> others 6 others 7 .... precisely, that is the length of the fusion
> sequence
>>> they have been adapted to (a compile-time constant)
>>>
>>> is there a way to create the sequence _1 to _n from this compile-time
>>> constant, and pass it to operator() of newDerived,
>>> then in the body of operator() use fusion::copy ?
>>
>>
>> That (almost) was what I was thinking of. Here is my suggestion:
>>
>> template < class Derived >
>> struct newDerived_
>> {
>> typedef void result_type;
>>
>> template < class Attributes >
>> void operator( Base*& p, const Attributes& attrs )
>> {
>> p = new Derived;
>> fusion::copy( attrs, *p );
>> }
>> };
>>
>> phoenix::function<newDerived_<Derived1> > newDerived1;
>> phoenix::function<newDerived_<Derived2> > newDerived2;
>> // and so on, don't know if there is a better way -- a 'templated'
>> phoenix::function?
>>
>> qi::rule< std::string::iterator, Base* () > r[ 10 ];
>> r[0] = (double_ >> int_>> ...)[newDerived1(_val, _0)];
>> r[1] = (double_ >> char_>> ...)[newDerived2(_val, _0)];
>> // ...
>>
>> Or maybe you could do this way:
>>
>> qi::rule< std::string::iterator, Derived1* () > r1;
>> qi::rule< std::string::iterator, Derived2* () > r2;
>> // ...
>>
>> struct newDerived_
>> {
>> typedef void result_type;
>>
>> template < class Derived, class Attributes >
>> void operator( Derived*& p, const Attributes& attrs )
>> {
>> p = new Derived;
>> fusion::copy( attrs, *p );
>> }
>> };
>>
>> phoenix::function<newDerived_> newDerived;
>>
>> r1 = (double_ >> int_>> ...)[newDerived(_val, _0)];
>> r2 = (double_ >> char_>> ...)[newDerived(_val, _0)];
>> // ...
>>
>> qi::rule< std::string::iterator, Base* () > r = r1 | r2 | ... ;
>>
>> HTH,
>> Gevorg
>
> That is great.
>
> I didn't know _0 was the whole list of attributes together as a fusion
> sequence.
>
> cool, thanks very much,
>
>
>
> ------------------------------------------------------------------------------
> What You Don't Know About Data Connectivity CAN Hurt You
> This paper provides an overview of data connectivity, details
> its effect on application quality, and explores various alternative
> solutions. http://p.sf.net/sfu/progress-d2d
I've just come up with another solution to your problem which might be
interesting in other such cases: use the attribute transformation
feature of spirit.
You need to define this template:
namespace boost { namespace spirit { namespace traits
{
template <typename T,typename S>
struct transform_attribute<T*, S, qi::domain>
{
typedef S& type;
static S& pre(T*& d) { d = new S(); return *static_cast<S*>(d); }
static void post(T*& val, S const& attr) { }
static void fail(T*& d) { delete d; }
};
}}}
which can then be used like this:
r1 = boost::spirit::attr_cast<base_type*, derived1>(double_ >> int_>> ...);
Regards,
Thomas Bernard
|