Boost logo

Boost Users :

Subject: Re: [Boost-users] Please help with metaprogramming question : termination of recursion
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-07-08 20:40:37


> I'm using Fusion to create a list of Range objects. Here is a simple
> function:
>
> using namespace boost::fusion;
>
> template <typename STLCollection, typename FusB, typename
> FusE>
> void process_append (STLCollection& collection, const FusB&
> begin, const FusE& end)
> {
> std::cout << "Yip! ";
> typename result_of::deref<FusB>::type r= deref(begin);
> /*23*/ collection.insert (collection.end(), boost::begin(r),
> boost::end(r));
> typename result_of::next<FusB>::type successor=
> next(begin);
> /*25*/ if (successor != end) process_append (collection,
> successor, end);
> std::cout << "Yap! ";
> }
>
> I expect it to print Yip! n times and then Yap! n times. What I get is a
> compiler error concerning the boost::begin(r) or boost::end(r), that I'm
> calling it on a fusion::void_ rather than a Range. As you see, I have
> moved the end-of-recusion test from its normal position at the top of the
> function (test when called, and return immediately rather than doing the
> normal body) to the point of the recursive call (don't call with the end
> sentinel). However, this appears to still trigger the function expansion,
> since the trail of errors seems to go from the point marked 23 as the
> original (inner-most) error, to several stops at point 25, to the caller,
> and so on back out. So it expands several times and then errors, so I
> think it is objecting to the "end" case.
>
> Now if simply mentioning the function, not calling it, is enough to make
> it expand the function, then more levels of indirection isn't going to
> help. What is the proper way to do this? Is there, somewhere, a proper
> example of using Fusion to iterate from begin to end of a Fusion
> collection? Presumably this must be done using recursion because the type
> of "next(I)" is not necessarily the same as the type of "I".
>
> If some other kind of overloading or partial specialization is the trick,
> I would expect that the "end" type, or the dereference of the "end" type,
> would be documented as something I could easily use for that.

You need to decide what function to call based on the _type_ of the fusion
iterators:

template <typename STLCollection, typename FusB, typename FusE>
void process_append (STLCollection& collection, const FusB& begin, const
FusE& end,
    mpl::true_)
{
    // do nothing
}

template <typename STLCollection, typename FusB, typename FusE>
void process_append (STLCollection& collection, const FusB& begin, const
FusE& end,
    mpl::false_)
   {
   std::cout << "Yip! ";
   typename result_of::deref<FusB>::type r= deref(begin);
   collection.insert (collection.end(), boost::begin(r), boost::end(r));
   typename result_of::next<FusB>::type successor= next(begin);
   process_append (collection, successor, end,
       is_same< typename result_of::next<FusB>::type, FusE>());
   std::cout << "Yap! ";
   }

template <typename STLCollection, typename FusB, typename FusE>
void process_append (STLCollection& collection, const FusB& begin, const
FusE& end)
{
    process_append(collection, begin, end, is_same<FusB, FusE>());
}

Regards Hartmut

---------------
Meet me at BoostCon
www.boostcon.com

>
> Please help.
> Thanks in advance,
>
> --John
>
>
> 2>D:\boost_1_43_0\boost/range/iterator.hpp(63) : error C2039: 'type' : is
> not a member of 'boost::mpl::eval_if_c<C,F1,F2>'
> 2> with
> 2> [
> 2> C=true,
> 2> F1=boost::range_const_iterator<boost::fusion::void_>,
> 2> F2=boost::range_mutable_iterator<const boost::fusion::void_>
> 2> ]
> 2> blahblahblah.h(23) : see reference to class template
> instantiation 'boost::range_iterator<C>' being compiled
> 2> with
> 2> [
> 2> C=const boost::fusion::void_
> 2> ]
> 2> blahblahblah.h(25) : see reference to function template
> instantiation 'void
> Aa::catranges_help::process_append<STLCollection,boost::fusion::cons_itera
> tor<const boost::fusion::nil>,FusE>(STLCollection &,const FusB &,const
> FusE &)' being compiled
> 2> with
> 2> [
> 2> STLCollection=std::vector<RTPRICEREC>,
> 2> FusE=boost::fusion::cons_iterator<const boost::fusion::nil>,
> 2> FusB=boost::fusion::cons_iterator<const boost::fusion::nil>
> 2> ]
> 2> blahblahblah.h(25) : see reference to function template
> instantiation 'void
> Aa::catranges_help::process_append<STLCollection,boost::fusion::cons_itera
> tor<Cons>,FusE>(STLCollection &,const FusB &,const FusE &)' being compiled
> 2> with
> 2> [
> 2> STLCollection=std::vector<RTPRICEREC>,
> 2> Cons=const
> boost::fusion::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::
> allocator<RTPRICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocat
> or<RTPRICEREC>>>,boost::fusion::nil>,
> 2> FusE=boost::fusion::cons_iterator<const boost::fusion::nil>,
> 2> FusB=boost::fusion::cons_iterator<const
> boost::fusion::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::
> allocator<RTPRICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocat
> or<RTPRICEREC>>>,boost::fusion::nil>>
> 2> ]
> 2> blahblahblah.h(25) : see reference to function template
> instantiation 'void
> Aa::catranges_help::process_append<STLCollection,boost::fusion::cons_itera
> tor<Cons>,FusE>(STLCollection &,const FusB &,const FusE &)' being compiled
> 2> with
> 2> [
> 2> STLCollection=std::vector<RTPRICEREC>,
> 2> Cons=const
> boost::fusion::cons<std::vector<RTPRICEREC>,boost::fusion::cons<std::pair<
> std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC>>,std::_V
> ector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC>>>,boost::fusion
> ::nil>>,
>
>
> 2> FusE=boost::fusion::cons_iterator<const boost::fusion::nil>,
> 2> FusB=boost::fusion::cons_iterator<const
> boost::fusion::cons<std::vector<RTPRICEREC>,boost::fusion::cons<std::pair<
> std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC>>,std::_V
> ector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC>>>,boost::fusion
> ::nil>>>
> 2> ]
> 2> blahblahblah.h(55) : see reference to function template
> instantiation 'void
> Aa::catranges_help::process_append<std::vector<_Ty>,boost::fusion::cons_it
> erator<Cons>,boost::fusion::cons_iterator<const
> boost::fusion::nil>>(STLCollection &,const FusB &,const FusE &)' being
> compiled
> 2> with
> 2> [
> 2> _Ty=RTPRICEREC,
> 2> Cons=const
> boost::fusion::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::
> allocator<RTPRICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocat
> or<RTPRICEREC>>>,boost::fusion::cons<std::vector<RTPRICEREC>,boost::fusion
> ::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTP
> RICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC
> >>>,boost::fusion::nil>>>,
> 2> STLCollection=std::vector<RTPRICEREC>,
> 2> FusB=boost::fusion::cons_iterator<const
> boost::fusion::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::
> allocator<RTPRICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocat
> or<RTPRICEREC>>>,boost::fusion::cons<std::vector<RTPRICEREC>,boost::fusion
> ::cons<std::pair<std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTP
> RICEREC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC
> >>>,boost::fusion::nil>>>>,
> 2> FusE=boost::fusion::cons_iterator<const boost::fusion::nil>
> 2> ]
> 2> blahblahblah.h(53) : while compiling class template member
> function 'Aa::catranges_help::object<R,Tail>::operator
> std::vector<_Ty>(void) const'
> 2> with
> 2> [
> 2>
> R=std::pair<std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICER
> EC>>,std::_Vector_const_iterator<RTPRICEREC,std::allocator<RTPRICEREC>>>,
> 2>
>
>
> TradeStation Group, Inc. is a publicly-traded holding company (NASDAQ GS:
> TRAD) of three operating subsidiaries, TradeStation Securities, Inc.
> (Member NYSE, FINRA, SIPC and NFA), TradeStation Technologies, Inc., a
> trading software and subscription company, and TradeStation Europe
> Limited, a United Kingdom, FSA-authorized introducing brokerage firm. None
> of these companies provides trading or investment advice, recommendations
> or endorsements of any kind. The information transmitted is intended only
> for the person or entity to which it is addressed and may contain
> confidential and/or privileged material. Any review, retransmission,
> dissemination or other use of, or taking of any action in reliance upon,
> this information by persons or entities other than the intended recipient
> is prohibited. If you received this in error, please contact the sender
> and delete the material from any computer.
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net