zip to shortest of collection of variable length seqs@

[SVN r35517]
This commit is contained in:
Dan Marsden
2006-10-07 15:43:33 +00:00
parent 7cd89c8d9c
commit 521574b39d
3 changed files with 36 additions and 56 deletions

View File

@ -9,12 +9,17 @@
#if !defined(FUSION_END_IMPL_20060123_2208)
#define FUSION_END_IMPL_20060123_2208
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/sequence/view/zip_view/zip_view_iterator_fwd.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/sequence/intrinsic/front.hpp>
#include <boost/fusion/iterator/advance.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/min.hpp>
namespace boost { namespace fusion {
@ -22,29 +27,30 @@ namespace boost { namespace fusion {
namespace detail
{
struct poly_end
template<typename M>
struct endpoints
{
template<typename SeqRef>
struct result
: result_of::end<typename remove_reference<SeqRef>::type>
{
BOOST_MPL_ASSERT((is_reference<SeqRef>));
typedef typename remove_reference<SeqRef>::type Seq;
typedef typename result_of::begin<Seq>::type begin;
typedef typename result_of::advance<begin, M>::type type;
};
template<typename Seq>
typename result<Seq&>::type
operator()(Seq& seq) const
{
return fusion::end(seq);
return fusion::advance<M>(fusion::begin(seq));
}
template<typename Seq>
typename result<Seq const&>::type
operator()(Seq const& seq) const
operator()(Seq const& seq)
{
return fusion::end(seq);
return fusion::advance<M>(fusion::begin(seq));
}
};
}
@ -60,19 +66,16 @@ namespace boost { namespace fusion {
struct apply
{
typedef zip_view_iterator<
typename result_of::transform<typename Sequence::sequences, detail::poly_end>::type,
typename result_of::transform<typename Sequence::sequences, detail::endpoints<typename Sequence::size> >::type,
typename Sequence::category> type;
static type
call(Sequence& sequence)
{
return type(
fusion::transform(sequence.sequences_, detail::poly_end()));
fusion::transform(sequence.sequences_, detail::endpoints<typename Sequence::size>()));
}
};
};
}
}}

View File

@ -9,38 +9,9 @@
#if !defined(FUSION_SIZE_IMPL_20060124_0800)
#define FUSION_SIZE_IMPL_20060124_0800
#include <boost/fusion/support/category_of.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/sequence/intrinsic/value_at.hpp>
#include <boost/fusion/algorithm/query/find_if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost { namespace fusion {
struct zip_view_tag;
struct random_access_iterator_tag;
namespace detail
{
template<typename Sequence>
struct zip_view_size
{
typedef result_of::find_if<
typename Sequence::sequences,
is_same<traits::category_of<remove_reference<mpl::_> >, random_access_iterator_tag> > finder;
typedef typename remove_reference<typename mpl::eval_if<
result_of::equal_to<typename finder::type, typename result_of::end<typename Sequence::sequences>::type>,
result_of::value_at_c<typename Sequence::sequences, 0>,
result_of::deref<typename finder::type> >::type>::type best_sequence;
typedef typename fusion::result_of::size<best_sequence> type;
};
}
namespace extension
{
@ -55,7 +26,7 @@ namespace boost { namespace fusion {
{
template<typename Sequence>
struct apply
: detail::zip_view_size<Sequence>::type
: Sequence::size
{};
};
}

View File

@ -44,22 +44,28 @@ namespace boost { namespace fusion {
: fusion::result_of::equal_to<typename fusion::result_of::find_if<Sequences, mpl::not_<is_reference<mpl::_> > >::type, typename fusion::result_of::end<Sequences>::type>
{};
template<typename Sequences>
struct all_same_size_impl
struct seq_ref_size
{
typedef mpl::transform_view<Sequences, fusion::result_of::size<remove_reference<mpl::_> > > sizes;
typedef typename mpl::at_c<sizes, 0>::type first_size;
typedef mpl::iterator_range<
typename mpl::next<typename mpl::begin<sizes>::type>::type,
typename mpl::end<sizes>::type> remainder;
typedef typename mpl::find_if<remainder, mpl::not_<is_same<mpl::_, first_size> > >::type found_difference;
typedef typename is_same<found_difference, typename mpl::end<remainder>::type>::type type;
template<typename Seq>
struct result
: result_of::size<typename remove_reference<Seq>::type>
{};
};
struct poly_min
{
template<typename Lhs, typename Rhs>
struct result
: mpl::min<Lhs, Rhs>
{};
};
template<typename Sequences>
struct all_same_size
: all_same_size_impl<Sequences>::type
{};
struct min_size
{
typedef typename result_of::transform<Sequences, detail::seq_ref_size>::type sizes;
typedef typename result_of::fold<sizes, typename result_of::front<sizes>::type, detail::poly_min>::type type;
};
}
struct zip_view_tag;
@ -69,12 +75,12 @@ namespace boost { namespace fusion {
struct zip_view : sequence_base< zip_view<Sequences> >
{
BOOST_MPL_ASSERT((detail::all_references<Sequences>));
BOOST_MPL_ASSERT((detail::all_same_size<Sequences>));
typedef typename detail::strictest_traversal<Sequences>::type category;
typedef zip_view_tag fusion_tag;
typedef fusion_sequence_tag tag; // this gets picked up by MPL
typedef mpl::true_ is_view;
typedef typename fusion::result_of::as_vector<Sequences>::type sequences;
typedef typename detail::min_size<Sequences>::type size;
zip_view(
const Sequences& seqs)