
Max Motovilov wrote:
I am not sure if this approach can be generalized to an arbitrary number of sequences. Perhaps it can be, by making the whole thing a recursive template instead of 3 separate ones. I'd try it just to see which version results in simpler code (gut feeling: the recursive template) and in faster compilation times (gut feeling: my current implementation) but customers and management are jointly snapping at my heels...
Against my better instincts I got drawn into this exercise... and I am now officially stumped. Since we have this thread, perhaps one of the MPL gurus would chime in. Here's the [entire!] code that uses the accumulator idiom:
===================================================================
template< typename S, typename A> struct product_view_ex : public if_< typename empty<S>::type, typename push_front< S, A >::type, transform_view< typename front<S>::type, product_view_ex< typename pop_front<S>::type, push_front<A,_1> > >
::type { typedef product_view_ex type; };
template< typename S> struct product_view : public if_< typename empty<S>::type, S, product_view_ex< S, typename clear<S>::type >
::type { typedef product_view type; };
===================================================================
The problem is that "if_< typename empty<S>::type ...." appears to always evaluate its "else" clause. Or, in other words [I think] empty<S>::type never evaluates as false_, even when the type of S is clearly an empty sequence (vector0<>) according to compiler messages. I am definitely missing something, but what?
The problem is that even when the sequence is empty, the pop_front<S>::type will still be evaluated. The if_ is working correctly, it's just that the compiler doesn't "know" about mpl::if_ and has to work out the template arguments even if they are not used. The following is still not quite right but it's closer. #include <boost/mpl/if.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/transform_view.hpp> #include <boost/mpl/back_inserter.hpp> #include <boost/mpl/push_front.hpp> #include <boost/mpl/pop_front.hpp> #include <boost/mpl/clear.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/empty.hpp> #include <boost/mpl/front.hpp> #include <boost/mpl/copy.hpp> using namespace boost::mpl; namespace mpl = boost::mpl; template< typename S, typename A> struct product_view_ex; template< typename S, typename A> struct product_view_ex_impl : public transform_view< typename front<S>::type, product_view_ex< typename pop_front<S>::type, push_front<A,_1> > > { }; template< typename S, typename A> struct product_view_ex : public eval_if<empty<S>, push_front< S, A >, product_view_ex_impl<S, A> > { }; template< typename S> struct product_view : public if_< typename empty<S>::type, S, product_view_ex< S, typename clear<S>::type > >::type { typedef product_view type; }; template<class T> struct print {}; int main() { typedef product_view<mpl::vector<mpl::range_c<int, 0, 2>, mpl::range_c<int, 3, 5> > > view; typedef print<mpl::fold<view, vector0<>, mpl::copy<_2, mpl::back_inserter<_1> > >::type>::type type; } In Christ, Steven Watanabe