|
Boost : |
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-03-12 18:05:27
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk