diff --git a/include/boost/fusion/algorithm/iteration/ext_/fold_s.hpp b/include/boost/fusion/algorithm/iteration/ext_/fold_s.hpp new file mode 100644 index 00000000..78d5d8e8 --- /dev/null +++ b/include/boost/fusion/algorithm/iteration/ext_/fold_s.hpp @@ -0,0 +1,77 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_FOLD_S_HPP_INCLUDED) +#define BOOST_FUSION_FOLD_S_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct segmented_fold_fun + { + template + struct result; + + template + struct result + { + typedef + fusion::result< + typename result_of::fold::type, + continue_ + > + type; + }; + + explicit segmented_fold_fun(Fun const& f) + : fun(f) + {} + + template + typename result::type + operator()(Range& rng, State const& state, Context const&) const + { + return fusion::fold(rng, state.value, fun); + } + + Fun const& fun; + }; + +}}} + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct fold_s + : result_of::segmented_fold_until< + Sequence, + State, + detail::segmented_fold_fun + > + {}; + } + + template + typename result_of::fold_s::type + fold_s(Sequence& seq, State const& state, F const& f) + { + return fusion::segmented_fold_until(seq, state, detail::segmented_fold_fun(f)); + } + + template + typename result_of::fold_s::type + fold_s(Sequence const& seq, State const& state, F const& f) + { + return fusion::segmented_fold_until(seq, state, detail::segmented_fold_fun(f)); + } +}} + +#endif diff --git a/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp b/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp old mode 100755 new mode 100644 index 9e571d0f..cf9d72c2 --- a/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp +++ b/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp @@ -1,65 +1,37 @@ /*============================================================================= - Copyright (c) 2006 Eric Niebler + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_FOR_EACH_S_05022006_1027) -#define FUSION_FOR_EACH_S_05022006_1027 +#if !defined(BOOST_FUSION_FOR_EACH_S_HPP_INCLUDED) +#define BOOST_FUSION_FOR_EACH_S_HPP_INCLUDED -#include -#include +#include #include -#include -#include - -// fwd declarations -namespace boost { namespace fusion -{ - template - void - for_each_s(Sequence& seq, F const& f); - - template - void - for_each_s(Sequence const& seq, F const& f); -}} +#include namespace boost { namespace fusion { namespace detail { - template - struct for_each_s_bind + template + struct segmented_for_each_fun { - explicit for_each_s_bind(F const &f) - : f_(f) + typedef result result_type; + + explicit segmented_for_each_fun(Fun const& f) + : fun(f) {} - template - void operator ()(Sequence &seq) const + template + result_type operator()(Range& rng, State const&, Context const&) const { - fusion::for_each_s(seq, this->f_); + fusion::for_each(rng, fun); + return void_(); } - template - void operator ()(Sequence const &seq) const - { - fusion::for_each_s(seq, this->f_); - } - private: - F const &f_; + Fun const& fun; }; - template - void for_each_s(Sequence &seq, F const &f, mpl::true_) - { - fusion::for_each_s(fusion::segments(seq), for_each_s_bind(f)); - } - - template - void for_each_s(Sequence &seq, F const &f, mpl::false_) - { - fusion::for_each(seq, f); - } }}} namespace boost { namespace fusion @@ -77,14 +49,14 @@ namespace boost { namespace fusion inline void for_each_s(Sequence& seq, F const& f) { - detail::for_each_s(seq, f, traits::is_segmented()); + fusion::segmented_fold_until(seq, void_(), detail::segmented_for_each_fun(f)); } template inline void for_each_s(Sequence const& seq, F const& f) { - detail::for_each_s(seq, f, traits::is_segmented()); + fusion::segmented_fold_until(seq, void_(), detail::segmented_for_each_fun(f)); } }} diff --git a/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp b/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp old mode 100755 new mode 100644 index 0b1852a6..85c1fd86 --- a/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp +++ b/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp @@ -1,188 +1,58 @@ /*============================================================================= - Copyright (c) 2006 Eric Niebler + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FIND_IF_S_05152006_1027) -#define FIND_IF_S_05152006_1027 +#if !defined(BOOST_FUSION_FIND_IF_S_HPP_INCLUDED) +#define BOOST_FUSION_FIND_IF_S_HPP_INCLUDED -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include - -// fwd declarations -namespace boost { namespace fusion -{ - namespace detail - { - template::value> - struct static_find_if_s_recurse; - } - - namespace result_of - { - template - struct find_if_s; - } -}} +#include namespace boost { namespace fusion { namespace detail { - - template::value> - struct is_found - : mpl::not_::type> > - {}; - - template - struct is_found - : mpl::not_ > - {}; - - template< - typename SegmentedRange - , typename Where - , typename Sequence = typename remove_reference< - typename result_of::deref< - typename SegmentedRange::iterator_type - >::type - >::type - , bool IsSegmented = traits::is_segmented::value - > - struct as_segmented_cons + template + struct segmented_find_if_fun { - typedef cons< - SegmentedRange - , cons > - > type; + template + struct result; - static type call(SegmentedRange const &range, Where const &where) + template + struct result { - return fusion::make_cons( - range - , fusion::make_cons( - segmented_range(*fusion::begin(range), where) - ) - ); + typedef + typename result_of::find_if::type + iterator_type; + + typedef + typename result_of::make_segmented_iterator< + iterator_type, + typename remove_const::type + >::type + segmented_iterator_type; + + typedef + typename mpl::if_< + result_of::equal_to< + iterator_type, + typename result_of::end::type + >, + fusion::result, // NOT FOUND + fusion::result // FOUND + >::type + type; + }; + + template + typename result::type + operator()(Range& rng, State const&, Context const& context) const + { + return fusion::make_segmented_iterator(fusion::find_if(rng), context); } }; - template< - typename SegmentedRange - , typename Where - , typename Sequence - > - struct as_segmented_cons - { - typedef cons type; - - static type call(SegmentedRange const &range, Where const &where) - { - return fusion::make_cons(range, where); - } - }; - - template< - typename SegmentedRange - , typename Pred - , bool IsEmpty = is_empty::value - > - struct static_find_if_s_seg - { - typedef typename SegmentedRange::iterator_type first; - typedef typename result_of::deref::type segment_ref; - typedef typename remove_reference::type segment; - typedef static_find_if_s_recurse where; - typedef range_next next; - typedef is_found is_found; - typedef as_segmented_cons found; - typedef static_find_if_s_seg not_found; - typedef typename mpl::eval_if::type type; - - static type call(SegmentedRange const &range) - { - return call_(range, is_found()); - } - - private: - static type call_(SegmentedRange const &range, mpl::true_) - { - return found::call(range, where::call(*range.where_)); - } - - static type call_(SegmentedRange const &range, mpl::false_) - { - return not_found::call(next::call(range)); - } - }; - - template< - typename SegmentedRange - , typename Pred - > - struct static_find_if_s_seg - { - typedef nil type; - - static type call(SegmentedRange const &) - { - return nil(); - } - }; - - template - struct static_find_if_s_recurse - { - typedef typename as_segmented_range::type range; - typedef static_find_if_s_seg find_if; - typedef typename find_if::type type; - - static type call(Sequence &seq) - { - return find_if::call(range(fusion::segments(seq))); - } - }; - - template - struct static_find_if_s_recurse - { - typedef typename result_of::find_if::type type; - - static type call(Sequence &seq) - { - return fusion::find_if(seq); - } - }; - - template::value> - struct static_find_if_s - : static_find_if_s_recurse - {}; - - template - struct static_find_if_s - { - typedef typename as_segmented_range::type range; - typedef static_find_if_s_recurse find_if; - typedef typename find_if::type found; - - typedef segmented_iterator::type> type; - - static type call(Sequence &seq) - { - return type(reverse_cons::call(find_if::call(seq))); - } - }; }}} namespace boost { namespace fusion @@ -191,31 +61,22 @@ namespace boost { namespace fusion { template struct find_if_s - { - typedef typename - detail::static_find_if_s< - Sequence - , Pred - >::type - type; - }; + : result_of::segmented_fold_until > + {}; } template - typename lazy_disable_if< - is_const - , result_of::find_if_s - >::type + typename result_of::find_if_s::type find_if_s(Sequence& seq) { - return detail::static_find_if_s::call(seq); + return fusion::segmented_fold_until(seq, void_(), detail::segmented_find_if_fun()); } template typename result_of::find_if_s::type find_if_s(Sequence const& seq) { - return detail::static_find_if_s::call(seq); + return fusion::segmented_fold_until(seq, void_(), detail::segmented_find_if_fun()); } }} diff --git a/include/boost/fusion/algorithm/query/ext_/find_s.hpp b/include/boost/fusion/algorithm/query/ext_/find_s.hpp new file mode 100644 index 00000000..8ccf202d --- /dev/null +++ b/include/boost/fusion/algorithm/query/ext_/find_s.hpp @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_FIND_S_HPP_INCLUDED) +#define BOOST_FUSION_FIND_S_HPP_INCLUDED + +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct segmented_find_fun + { + template + struct result; + + template + struct result + { + typedef + typename result_of::find::type + iterator_type; + + typedef + typename result_of::make_segmented_iterator< + iterator_type, + typename remove_const::type + >::type + segmented_iterator_type; + + typedef + typename mpl::if_< + result_of::equal_to< + iterator_type, + typename result_of::end::type + >, + fusion::result, // NOT FOUND + fusion::result // FOUND + >::type + type; + }; + + template + typename result::type + operator()(Range& rng, State const&, Context const& context) const + { + return fusion::make_segmented_iterator(fusion::find(rng), context); + } + }; + +}}} + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct find_s + : result_of::segmented_fold_until > + {}; + } + + template + typename result_of::find_s::type + find_s(Sequence& seq) + { + return fusion::segmented_fold_until(seq, void_(), detail::segmented_find_fun()); + } + + template + typename result_of::find_s::type + find_s(Sequence const& seq) + { + return fusion::segmented_fold_until(seq, void_(), detail::segmented_find_fun()); + } +}} + +#endif diff --git a/include/boost/fusion/container/ext_/tree.hpp b/include/boost/fusion/container/ext_/tree.hpp old mode 100755 new mode 100644 index cd8c5dcd..1958df3c --- a/include/boost/fusion/container/ext_/tree.hpp +++ b/include/boost/fusion/container/ext_/tree.hpp @@ -18,26 +18,18 @@ #include // for nil #include #include +#include #include +#include #include #include +#include +#include namespace boost { namespace fusion { struct tree_tag; - namespace detail - { - template - struct reference : add_reference {}; - - template - struct reference : reference::type, false> {}; - - template - struct reference : reference {}; - } - template struct tree : sequence_base > @@ -46,7 +38,7 @@ namespace boost { namespace fusion typedef Left left_type; typedef Right right_type; typedef tree_tag fusion_tag; - typedef forward_traversal_tag category; + typedef bidirectional_traversal_tag category; typedef mpl::false_ is_view; typedef typename mpl::if_< @@ -124,6 +116,15 @@ namespace boost { namespace fusion : segmented_end {}; }; + + template<> + struct size_impl + { + template + struct apply + : segmented_size::type + {}; + }; } }} diff --git a/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp b/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp old mode 100755 new mode 100644 index 58f148f2..16f2bfa4 --- a/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp +++ b/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp @@ -4,8 +4,8 @@ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_SEGMENTS_04052005_1141) -#define FUSION_SEGMENTS_04052005_1141 +#if !defined(BOOST_FUSION_SEGMENTS_04052005_1141) +#define BOOST_FUSION_SEGMENTS_04052005_1141 #include @@ -27,9 +27,10 @@ namespace boost { namespace fusion template struct segments { + typedef typename traits::tag_of::type tag_type; + typedef typename - extension::segments_impl::type>:: - template apply::type + extension::segments_impl::template apply::type type; }; } @@ -38,18 +39,16 @@ namespace boost { namespace fusion typename result_of::segments::type segments(Sequence & seq) { - return - extension::segments_impl::type>:: - template apply::call(seq); + typedef typename traits::tag_of::type tag_type; + return extension::segments_impl::template apply::call(seq); } template typename result_of::segments::type segments(Sequence const& seq) { - return - extension::segments_impl::type>:: - template apply::call(seq); + typedef typename traits::tag_of::type tag_type; + return extension::segments_impl::template apply::call(seq); } }} diff --git a/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp b/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp index 8b61746a..d152efe0 100644 --- a/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp +++ b/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp @@ -1,57 +1,57 @@ /*============================================================================= - Copyright (c) 2006 Eric Niebler + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_SIZE_S_08112006_1141) -#define FUSION_SIZE_S_08112006_1141 +#if !defined(BOOST_FUSION_SIZE_S_08112006_1141) +#define BOOST_FUSION_SIZE_S_08112006_1141 +#include +#include +#include #include #include -#include -#include -#include +#include +#include +#include #include +#include namespace boost { namespace fusion { /////////////////////////////////////////////////////////////////////////// // calculates the size of any segmented data structure. - template::value> + template struct segmented_size; namespace detail { - struct size_plus - { - template - struct result; + /////////////////////////////////////////////////////////////////////////// + template::value> + struct segmented_size_impl + : mpl::fold< + typename remove_reference< + typename add_const< + typename result_of::segments::type + >::type + >::type, + mpl::size_t<0>, + mpl::plus > + >::type + {}; - template - struct result - : mpl::plus< - segmented_size::type> - , typename remove_reference::type - > - {}; - }; + template + struct segmented_size_impl + : result_of::size::type + {}; } - /////////////////////////////////////////////////////////////////////////// - template + template struct segmented_size - : result_of::fold< - typename result_of::segments::type - , mpl::size_t<0> - , detail::size_plus - >::type + : detail::segmented_size_impl {}; - template - struct segmented_size - : result_of::size - {}; }} #endif diff --git a/include/boost/fusion/view/ext_/detail/begin_impl.hpp b/include/boost/fusion/view/ext_/detail/begin_impl.hpp new file mode 100644 index 00000000..d5fd90a3 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/begin_impl.hpp @@ -0,0 +1,100 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_BEGIN_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_BEGIN_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + struct segmented_begin_fun + { + template + struct result; + + template + struct result + { + typedef + iterator_range< + typename fusion::result_of::begin::type, + typename fusion::result_of::end::type + > + range_type; + + typedef + fusion::result< + cons::type>, + fusion::break_ + > + type; + }; + + template + typename result::type + operator()(Range& rng, State const&, Context const& context) const + { + typedef + iterator_range< + typename fusion::result_of::begin::type, + typename fusion::result_of::end::type + > + range_type; + + return fusion::make_cons(range_type(fusion::begin(rng), fusion::end(rng)), context); + } + }; + + template::type::value> + struct segmented_begin_impl + { + typedef + segmented_end_impl + end_impl; + + typedef + segmented_fold_until_impl< + Range, + result, + Stack, + segmented_begin_fun + > + fold_impl; + + typedef typename fold_impl::type::value_type type; + + static type call(Range& rng, Stack const& stack) + { + return fold_impl::call(rng, end_impl::call(rng, stack), stack, segmented_begin_fun()).value; + } + }; + + template + struct segmented_begin_impl + { + typedef typename result_of::begin::type begin_type; + typedef typename result_of::end::type end_type; + typedef iterator_range pair_type; + typedef cons type; + + static type call(Range& rng, Stack stack) + { + return type(pair_type(fusion::begin(rng), fusion::end(rng)), stack); + } + }; + +}}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/deref_impl.hpp b/include/boost/fusion/view/ext_/detail/deref_impl.hpp new file mode 100644 index 00000000..084aa521 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/deref_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_DEREF_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_ITERATOR_DEREF_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + struct segmented_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + //auto deref(it) + //{ + // return deref(begin(car(it.nodes))) + //} + template<> + struct deref_impl + { + template + struct apply + { + typedef + typename result_of::deref< + typename It::nodes_type::car_type::begin_type + >::type + type; + + static type call(It const& it) + { + return *it.nodes.car.first; + } + }; + }; + + } +}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/end_impl.hpp b/include/boost/fusion/view/ext_/detail/end_impl.hpp new file mode 100644 index 00000000..5e7eee56 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/end_impl.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_END_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_END_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + //auto segmented_end_impl( rng, stack ) + //{ + // assert(is_segmented(rng)); + // auto it = end(segments(rng)); + // return cons(iterator_range(it, it), stack); + //} + + template + struct segmented_end_impl + { + BOOST_MPL_ASSERT((traits::is_segmented)); + + typedef + typename result_of::end< + typename remove_reference< + typename add_const< + typename result_of::segments::type + >::type + >::type + >::type + end_type; + + typedef iterator_range pair_type; + typedef cons type; + + static type call(Range & rng, Stack stack) + { + end_type end = fusion::end(fusion::segments(rng)); + return type(pair_type(end, end), stack); + } + }; + +}}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/equal_to_impl.hpp b/include/boost/fusion/view/ext_/detail/equal_to_impl.hpp new file mode 100644 index 00000000..3b5bd7d5 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/equal_to_impl.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_EQUAL_TO_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_ITERATOR_EQUAL_TO_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct segmented_iterator_tag; + + namespace extension + { + template + struct equal_to_impl; + + template<> + struct equal_to_impl + { + // Compare all the segment iterators in each stack, starting with + // the bottom-most. + template + struct apply + : mpl::equal< + typename mpl::reverse_transform< + typename result_of::as_vector::type, + result_of::begin + >::type, + typename mpl::reverse_transform< + typename result_of::as_vector::type, + result_of::begin + >::type, + result_of::equal_to + > + {}; + }; + + } +}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/next_impl.hpp b/include/boost/fusion/view/ext_/detail/next_impl.hpp new file mode 100644 index 00000000..2e25d4e7 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/next_impl.hpp @@ -0,0 +1,252 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_NEXT_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_ITERATOR_NEXT_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct segmented_iterator_tag; + + template + struct segmented_iterator; + + namespace detail + { + //bool is_invalid(stack) + //{ + // return empty(car(stack)); + //} + + template + struct is_invalid + : result_of::empty + {}; + + ////Advance the first iterator in the range at the + ////top of a stack of iterator ranges. Return the + ////new stack. + //auto pop_front_car(stack) + //{ + // return cons(pop_front(car(stack)), cdr(stack)) + //} + + template + struct pop_front_car + { + typedef typename Stack::car_type car_type; + typedef typename result_of::pop_front::type new_car_type; + typedef cons type; + + static type call(Stack const & stack) + { + return type(fusion::pop_front(stack.car), stack.cdr); + } + }; + + template< + typename Stack, + typename Next = typename pop_front_car::type, + bool IsInvalid = is_invalid::value, + int StackSize = Stack::size::value> + struct segmented_next_impl_recurse; + + // Handle the case where the top of the stack has no usable + //auto segmented_next_impl_recurse3(stack) + //{ + // if (size(stack) == 1) + // return cons(iterator_range(end(car(stack)), end(car(stack))), nil); + // else + // return segmented_next_impl_recurse(stack.cdr); + //} + + template< + typename Stack, + int StackSize = Stack::size::value> + struct segmented_next_impl_recurse3 + { + typedef segmented_next_impl_recurse impl; + typedef typename impl::type type; + + static type call(Stack const & stack) + { + return impl::call(stack.cdr); + } + }; + + template + struct segmented_next_impl_recurse3 + { + typedef typename Stack::car_type::end_type end_type; + typedef iterator_range range_type; + typedef cons type; + + static type call(Stack const & stack) + { + return type(range_type(stack.car.last, stack.car.last)); + } + }; + + //auto segmented_next_impl_recurse2(stack) + //{ + // auto res = segmented_begin_impl(front(car(stack)), stack); + // if (is_invalid(res)) + // return segmented_next_impl_recurse3(stack); + // else + // return res; + //} + + template< + typename Stack, + typename Range = + typename remove_reference< + typename add_const< + typename result_of::deref::type + >::type + >::type, + typename Result = + typename segmented_begin_impl::type, + bool IsInvalid = + is_invalid::value> + struct segmented_next_impl_recurse2 + { + typedef segmented_next_impl_recurse3 impl; + typedef typename impl::type type; + + static type call(Stack const & stack) + { + return impl::call(stack); + } + }; + + template + struct segmented_next_impl_recurse2 + { + typedef Result type; + + static type call(Stack const & stack) + { + return segmented_begin_impl::call(*stack.car.first, stack); + } + }; + + //auto segmented_next_impl_recurse(stack) + //{ + // auto next = pop_front_car(stack); + // if (is_invalid(next)) + // if (1 == size(stack)) + // return next; + // else + // return segmented_next_impl_recurse(cdr(stack)); + // else + // return segmented_next_impl_recurse2(next) + //} + + template + struct segmented_next_impl_recurse + { + typedef + typename segmented_next_impl_recurse::type + type; + + static type call(Stack const& stack) + { + return segmented_next_impl_recurse::call(stack.cdr); + } + }; + + template + struct segmented_next_impl_recurse + { + typedef Next type; + + static type call(Stack const & stack) + { + return pop_front_car::call(stack); + } + }; + + template + struct segmented_next_impl_recurse + { + typedef segmented_next_impl_recurse2 impl; + typedef typename impl::type type; + + static type call(Stack const & stack) + { + return impl::call(pop_front_car::call(stack)); + } + }; + + //auto segmented_next_impl(stack) + //{ + // // car(stack) is a range of values, not a range of segments + // auto next = pop_front_car(stack); + // if (is_invalid(next)) + // return segmented_next_impl_recurse(cdr(next)); + // else + // return next; + //} + + template< + typename Stack, + typename Next = typename pop_front_car::type, + bool IsInvalid = is_invalid::value> + struct segmented_next_impl + { + typedef segmented_next_impl_recurse impl; + typedef typename impl::type type; + + static type call(Stack const & stack) + { + return impl::call(stack.cdr); + } + }; + + template + struct segmented_next_impl + { + typedef Next type; + + static type call(Stack const & stack) + { + return pop_front_car::call(stack); + } + }; + } + + namespace extension + { + template + struct next_impl; + + template<> + struct next_impl + { + template + struct apply + { + typedef detail::segmented_next_impl impl; + typedef segmented_iterator type; + + static type call(It const& it) + { + return type(impl::call(it.nodes)); + } + }; + }; + + } +}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/reverse_cons.hpp b/include/boost/fusion/view/ext_/detail/reverse_cons.hpp new file mode 100644 index 00000000..9f17b07e --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/reverse_cons.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_REVERSE_CONS_HPP_INCLUDED) +#define BOOST_FUSION_REVERSE_CONS_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + //////////////////////////////////////////////////////////////////////////// + template + struct reverse_cons; + + template + struct reverse_cons, State> + { + typedef reverse_cons > impl; + typedef typename impl::type type; + + static type call(cons const &cons, State const &state = State()) + { + return impl::call(cons.cdr, fusion::make_cons(cons.car, state)); + } + }; + + template + struct reverse_cons + { + typedef State type; + + static State const &call(nil const &, State const &state = State()) + { + return state; + } + }; +}}} + +#endif diff --git a/include/boost/fusion/view/ext_/detail/segment_sequence.hpp b/include/boost/fusion/view/ext_/detail/segment_sequence.hpp new file mode 100644 index 00000000..f68c31b8 --- /dev/null +++ b/include/boost/fusion/view/ext_/detail/segment_sequence.hpp @@ -0,0 +1,112 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_SEQUENCE_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_SEQUENCE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace detail + { + struct segment_sequence_tag {}; + + // Here, Sequence is a sequence of ranges (which may or may not be + // segmented). + template + struct segment_sequence + : sequence_base > + { + typedef fusion_sequence_tag tag; + typedef segment_sequence_tag fusion_tag; + typedef typename Sequence::is_view is_view; + typedef typename Sequence::category category; + typedef Sequence sequence_type; + sequence_type sequence; + + explicit segment_sequence(Sequence const & seq) + : sequence(seq) + {} + }; + } + + namespace extension + { + template + struct is_segmented_impl; + + template<> + struct is_segmented_impl + { + template + struct apply + : mpl::true_ + {}; + }; + + template + struct segments_impl; + + template<> + struct segments_impl + { + template + struct apply + { + typedef typename Sequence::sequence_type type; + + static type call(Sequence & seq) + { + return seq.sequence; + } + }; + }; + + template + struct begin_impl; + + template<> + struct begin_impl + { + template + struct apply + : segmented_begin + {}; + }; + + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply + : segmented_end + {}; + }; + + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply + : segmented_size::type + {}; + }; + + } +}} + +#endif diff --git a/include/boost/fusion/view/ext_/multiple_view.hpp b/include/boost/fusion/view/ext_/multiple_view.hpp deleted file mode 100755 index e34b1d62..00000000 --- a/include/boost/fusion/view/ext_/multiple_view.hpp +++ /dev/null @@ -1,178 +0,0 @@ -/*============================================================================= - Copyright (c) 2001-2006 Eric Niebler - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ -#ifndef FUSION_MULTIPLE_VIEW_05052005_0335 -#define FUSION_MULTIPLE_VIEW_05052005_0335 - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace fusion -{ - struct multiple_view_tag; - struct forward_traversal_tag; - struct fusion_sequence_tag; - - template - struct multiple_view - : sequence_base > - { - typedef multiple_view_tag fusion_tag; - typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef forward_traversal_tag category; - typedef mpl::true_ is_view; - typedef mpl::int_ size; - typedef T value_type; - - multiple_view() - : val() - {} - - explicit multiple_view(typename detail::call_param::type val) - : val(val) - {} - - value_type val; - }; - - template - inline multiple_view::type> - make_multiple_view(T const& v) - { - return multiple_view::type>(v); - } - - struct multiple_view_iterator_tag; - struct forward_traversal_tag; - - template - struct multiple_view_iterator - : iterator_base > - { - typedef multiple_view_iterator_tag fusion_tag; - typedef forward_traversal_tag category; - typedef typename MultipleView::value_type value_type; - typedef MultipleView multiple_view_type; - typedef Index index; - - explicit multiple_view_iterator(multiple_view_type const &view_) - : view(view_) - {} - - multiple_view_type view; - }; - - namespace extension - { - template - struct next_impl; - - template <> - struct next_impl - { - template - struct apply - { - typedef multiple_view_iterator< - typename mpl::next::type - , typename Iterator::multiple_view_type - > type; - - static type - call(Iterator const &where) - { - return type(where.view); - } - }; - }; - - template - struct end_impl; - - template <> - struct end_impl - { - template - struct apply - { - typedef multiple_view_iterator< - typename Sequence::size - , Sequence - > type; - - static type - call(Sequence &seq) - { - return type(seq); - } - }; - }; - - template - struct deref_impl; - - template <> - struct deref_impl - { - template - struct apply - { - typedef typename Iterator::value_type type; - - static type - call(Iterator const& i) - { - return i.view.val; - } - }; - }; - - template - struct begin_impl; - - template <> - struct begin_impl - { - template - struct apply - { - typedef multiple_view_iterator< - mpl::int_<0> - , Sequence - > type; - - static type - call(Sequence &seq) - { - return type(seq); - } - }; - }; - - template - struct value_of_impl; - - template <> - struct value_of_impl - { - template - struct apply - { - typedef typename Iterator::multiple_view_type multiple_view_type; - typedef typename multiple_view_type::value_type type; - }; - }; - } -}} - -#endif - - diff --git a/include/boost/fusion/view/ext_/segmented_begin.hpp b/include/boost/fusion/view/ext_/segmented_begin.hpp new file mode 100644 index 00000000..a0aa12e2 --- /dev/null +++ b/include/boost/fusion/view/ext_/segmented_begin.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_BEGIN_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_BEGIN_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + template + struct segmented_iterator; + + //auto segmented_begin( rng ) + //{ + // return make_segmented_iterator( segmented_begin_impl( rng, nil ) ); + //} + + template + struct segmented_begin + { + typedef + segmented_iterator< + typename detail::segmented_begin_impl::type + > + type; + + static type call(Range & rng) + { + return type( + detail::segmented_begin_impl::call(rng, fusion::nil())); + } + }; + +}} + +#endif diff --git a/include/boost/fusion/view/ext_/segmented_end.hpp b/include/boost/fusion/view/ext_/segmented_end.hpp new file mode 100644 index 00000000..e9ace31f --- /dev/null +++ b/include/boost/fusion/view/ext_/segmented_end.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_END_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_END_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + template + struct segmented_iterator; + + //auto segmented_end( rng ) + //{ + // return make_segmented_iterator( segmented_end_impl( rng ) ); + //} + + template + struct segmented_end + { + typedef + segmented_iterator< + typename detail::segmented_end_impl::type + > + type; + + static type call(Range & rng) + { + return type( + detail::segmented_end_impl::call(rng, fusion::nil())); + } + }; + +}} + +#endif diff --git a/include/boost/fusion/view/ext_/segmented_fold_until.hpp b/include/boost/fusion/view/ext_/segmented_fold_until.hpp new file mode 100644 index 00000000..85392073 --- /dev/null +++ b/include/boost/fusion/view/ext_/segmented_fold_until.hpp @@ -0,0 +1,436 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SEGMENTED_FOLD_UNTIL_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_FOLD_UNTIL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// fun(rng, state, context) +// rng: a non-segmented range +// state: the state of the fold so far +// context: the path to the current range +// +// returns: (state', fcontinue) + +namespace boost { namespace fusion +{ + template + struct segmented_iterator; + + namespace result_of + { + template + struct make_segmented_iterator + { + typedef + iterator_range< + Cur, + typename result_of::end< + typename remove_reference< + typename result_of::deref< + typename Context::car_type::begin_type + >::type + >::type + >::type + > + range_type; + + typedef + segmented_iterator > + type; + }; + } + + template + typename result_of::make_segmented_iterator::type + make_segmented_iterator(Cur const& cur, Context const& context) + { + typedef result_of::make_segmented_iterator impl_type; + typedef typename impl_type::type type; + typedef typename impl_type::range_type range_type; + return type(fusion::make_cons(range_type(cur, fusion::end(*context.car.first)), context)); + } + + typedef mpl::true_ continue_; + typedef mpl::false_ break_; + + template + struct result + { + typedef Value value_type; + typedef Continue continue_type; + + result(Value const& val) + : value(val) + {} + + value_type value; + }; + + template + struct result + { + typedef void_ value_type; + typedef Continue continue_type; + + result(void_ const&) + {} + + value_type value; + }; + + template + result make_result_continue(Value const& val) + { + return result(val); + } + + template + result make_result_break(Value const& val) + { + return result(val); + } + + namespace detail + { + template< + typename Begin, + typename End, + typename State, + typename Context, + typename Fun, + bool IsEmpty = result_of::empty< + typename result_of::value_of::type + >::type::value> + struct segmented_fold_until_iterate_skip_empty; + + template< + typename Begin, + typename End, + typename State, + typename Context, + typename Fun, + bool IsDone = result_of::equal_to::type::value> + struct segmented_fold_until_iterate; + + template< + typename Range, + typename State, + typename Context, + typename Fun, + bool IsSegmented = traits::is_segmented::type::value> + struct segmented_fold_until_impl; + + template + struct segmented_fold_until_on_segments; + + //auto push_context(cur, end, context) + //{ + // return push_back(context, segment_sequence(iterator_range(cur, end))); + //} + + template + struct push_context + { + typedef iterator_range range_type; + typedef cons type; + + static type call(Cur const& cur, End const& end, Context const& context) + { + return fusion::make_cons(range_type(cur, end), context); + } + }; + + //auto make_segmented_iterator(cur, end, context) + //{ + // return segmented_iterator(push_context(cur, end, context)); + //} + // + //auto segmented_fold_until_impl(rng, state, context, fun) + //{ + // if (is_segmented(rng)) + // { + // segmented_fold_until_on_segments(segments(rng), state, context, fun); + // } + // else + // { + // return fun(rng, state, context); + // } + //} + + template< + typename Range, + typename State, + typename Context, + typename Fun, + bool IsSegmented> + struct segmented_fold_until_impl + { + typedef + segmented_fold_until_on_segments< + typename remove_reference< + typename add_const< + typename result_of::segments::type + >::type + >::type, + State, + Context, + Fun + > + impl; + + typedef typename impl::type type; + + static type call(Range& rng, State const& state, Context const& context, Fun const& fun) + { + return impl::call(fusion::segments(rng), state, context, fun); + } + }; + + template< + typename Range, + typename State, + typename Context, + typename Fun> + struct segmented_fold_until_impl + { + typedef + typename boost::result_of::type + type; + + static type call(Range& rng, State const& state, Context const& context, Fun const& fun) + { + return fun(rng, state, context); + } + }; + + //auto segmented_fold_until_on_segments(segs, state, context, fun) + //{ + // auto cur = begin(segs), end = end(segs); + // for (; cur != end; ++cur) + // { + // if (empty(*cur)) + // continue; + // auto context` = push_context(cur, end, context); + // state = segmented_fold_until_impl(*cur, state, context`, fun); + // if (!second(state)) + // return state; + // } + //} + + template + struct segmented_fold_until_iterate_skip_empty + { + // begin != end and !empty(*begin) + typedef + push_context + push_context_impl; + + typedef + typename push_context_impl::type + next_context_type; + + typedef + segmented_fold_until_impl< + typename remove_reference< + typename add_const< + typename result_of::deref::type + >::type + >::type, + State, + next_context_type, + Fun + > + fold_recurse_impl; + + typedef + typename fold_recurse_impl::type + next_state_type; + + typedef + segmented_fold_until_iterate< + typename result_of::next::type, + End, + next_state_type, + Context, + Fun + > + next_iteration_impl; + + typedef + typename mpl::eval_if< + typename next_state_type::continue_type, + next_iteration_impl, + mpl::identity + >::type + type; + + static type call(Begin const& beg, End const& end, State const& state, + Context const& context, Fun const& fun) + { + return call(beg, end, state, context, fun, typename next_state_type::continue_type()); + } + + static type call(Begin const& beg, End const& end, State const& state, + Context const& context, Fun const& fun, mpl::true_) // continue + { + return next_iteration_impl::call( + fusion::next(beg), + end, + fold_recurse_impl::call( + *beg, + state, + push_context_impl::call(beg, end, context), + fun), + context, + fun); + } + + static type call(Begin const& beg, End const& end, State const& state, + Context const& context, Fun const& fun, mpl::false_) // break + { + return fold_recurse_impl::call( + *beg, + state, + push_context_impl::call(beg, end, context), + fun); + } + }; + + template + struct segmented_fold_until_iterate_skip_empty + { + typedef + segmented_fold_until_iterate< + typename result_of::next::type, + End, + State, + Context, + Fun + > + impl; + + typedef typename impl::type type; + + static type call(Begin const& beg, End const& end, State const& state, + Context const& context, Fun const& fun) + { + return impl::call(fusion::next(beg), end, state, context, fun); + } + }; + + template + struct segmented_fold_until_iterate + { + typedef + segmented_fold_until_iterate_skip_empty + impl; + + typedef typename impl::type type; + + static type call(Begin const& beg, End const& end, State const& state, + Context const& context, Fun const& fun) + { + return impl::call(beg, end, state, context, fun); + } + }; + + template + struct segmented_fold_until_iterate + { + typedef State type; + + static type call(Begin const&, End const&, State const& state, + Context const&, Fun const&) + { + return state; + } + }; + + template + struct segmented_fold_until_on_segments + { + typedef + segmented_fold_until_iterate< + typename result_of::begin::type, + typename result_of::end::type, + State, + Context, + Fun + > + impl; + + typedef typename impl::type type; + + static type call(Segments& segs, State const& state, Context const& context, Fun const& fun) + { + return impl::call(fusion::begin(segs), fusion::end(segs), state, context, fun); + } + }; + + } + + //auto segmented_fold_until(rng, state, fun) + //{ + // return first(segmented_fold_until_impl(rng, state, nil, fun)); + //} + + namespace result_of + { + template + struct segmented_fold_until + { + typedef + detail::segmented_fold_until_impl< + Range, + result, + fusion::nil, + Fun + > + impl; + + typedef + typename impl::type::value_type + type; + }; + } + + template + typename result_of::segmented_fold_until::type + segmented_fold_until(Range& rng, State const& state, Fun const& fun) + { + typedef typename result_of::segmented_fold_until::impl impl; + return impl::call(rng, state, fusion::nil(), fun).value; + } + + template + typename result_of::segmented_fold_until::type + segmented_fold_until(Range const& rng, State const& state, Fun const& fun) + { + typedef typename result_of::segmented_fold_until::impl impl; + return impl::call(rng, state, fusion::nil(), fun).value; + } +}} + +#endif diff --git a/include/boost/fusion/view/ext_/segmented_iterator.hpp b/include/boost/fusion/view/ext_/segmented_iterator.hpp index 79bc707e..cd454e27 100644 --- a/include/boost/fusion/view/ext_/segmented_iterator.hpp +++ b/include/boost/fusion/view/ext_/segmented_iterator.hpp @@ -1,448 +1,42 @@ /*============================================================================= - Copyright (c) 2006 Eric Niebler + Copyright (c) 2011 Eric Niebler - Use, modification and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#ifndef FUSION_SEGMENTED_ITERATOR_EAN_05032006_1027 -#define FUSION_SEGMENTED_ITERATOR_EAN_05032006_1027 +#if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_ITERATOR_HPP_INCLUDED -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for nil -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include namespace boost { namespace fusion { - struct fusion_sequence_tag; - - namespace detail - { - using mpl::_; - using mpl::not_; - - //////////////////////////////////////////////////////////////////////////// - template - struct is_empty - : result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type - > - {}; - - template - struct is_empty - : is_empty - {}; - - //////////////////////////////////////////////////////////////////////////// - struct not_is_empty_pred - { - template - struct apply - : not_ > - {}; - }; - - struct segmented_range_tag; - - //////////////////////////////////////////////////////////////////////////// - template - struct segmented_range - : sequence_base > - { - BOOST_MPL_ASSERT_NOT((is_reference)); - typedef mpl::bool_ is_segmented; - typedef segmented_range_tag fusion_tag; - typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef mpl::true_ is_view; - - // If this is a range of segments, skip over the empty ones - typedef typename mpl::if_< - is_segmented - , filter_view - , Sequence - >::type sequence_non_ref_type; - - typedef typename mpl::if_< - traits::is_view - , sequence_non_ref_type - , sequence_non_ref_type & - >::type sequence_type; - - typedef - typename fusion::result_of::advance< - typename fusion::result_of::begin::type - , Index - >::type - iterator_type; - - typedef typename traits::category_of::type category; - - explicit segmented_range(Sequence &sequence_) - : sequence(sequence_type(sequence_)) - {} - - segmented_range(sequence_type sequence_, int) - : sequence(sequence_) - {} - - iterator_type where_() const - { - return fusion::advance( - fusion::begin(const_cast(this->sequence)) - ); - } - - sequence_type sequence; - - private: - segmented_range &operator =(segmented_range const &); - }; - } - - namespace extension - { - template<> - struct is_segmented_impl - { - template - struct apply - : Sequence::is_segmented - {}; - }; - - template<> - struct size_impl - { - template - struct apply - : mpl::int_< - result_of::distance< - typename Sequence::iterator_type - , typename result_of::end::type - >::value - > - {}; - }; - - template<> - struct segments_impl - { - template - struct apply - { - typedef Sequence &type; - static type call(Sequence &seq) - { - return seq; - } - }; - }; - - template<> - struct begin_impl - { - template - struct apply - { - typedef typename Sequence::iterator_type type; - static type call(Sequence &seq) - { - return seq.where_(); - } - }; - }; - - template<> - struct end_impl - { - template - struct apply - { - typedef typename Sequence::sequence_non_ref_type sequence; - typedef typename result_of::end::type type; - - static type call(Sequence &seq) - { - return fusion::end(seq.sequence); - } - }; - }; - } - - namespace detail - { - /////////////////////////////////////////////////////////////////////// - template - struct range_next; - - template - struct range_next > - { - typedef typename mpl::next::type index_type; - typedef segmented_range type; - - static type call(segmented_range const &rng) - { - return type(rng.sequence, 0); - } - }; - - /////////////////////////////////////////////////////////////////////// - template - struct is_range_next_empty - : is_empty::type> - {}; - - template<> - struct is_range_next_empty - : mpl::true_ - {}; - - /////////////////////////////////////////////////////////////////////// - template::value> - struct as_segmented_range - { - typedef typename result_of::segments::type segments; - typedef typename remove_reference::type sequence; - typedef segmented_range, true> type; - - static type call(Sequence &seq) - { - segments segs(fusion::segments(seq)); - return type(segs); - } - }; - - template - struct as_segmented_range - { - typedef typename remove_reference::type sequence; - typedef segmented_range, false> type; - - static type call(Sequence &seq) - { - return type(seq); - } - }; - - template - struct as_segmented_range, IsSegmented> - { - typedef segmented_range type; - static type &call(type &seq) - { - return seq; - } - }; - - /////////////////////////////////////////////////////////////////////// - template< - typename Sequence - , typename State = nil - , bool IsSegmented = traits::is_segmented::value - > - struct push_segments - { - typedef typename as_segmented_range::type range; - typedef typename result_of::begin::type begin; - typedef typename result_of::deref::type next_ref; - typedef typename remove_reference::type next; - typedef push_segments > push; - typedef typename push::type type; - - static type call(Sequence &seq, State const &state) - { - range rng(as_segmented_range::call(seq)); - next_ref nxt(*fusion::begin(rng)); - return push::call(nxt, fusion::make_cons(rng, state)); - } - }; - - template - struct push_segments - { - typedef typename as_segmented_range::type range; - typedef cons type; - - static type call(Sequence &seq, State const &state) - { - range rng(as_segmented_range::call(seq)); - return fusion::make_cons(rng, state); - } - }; - - /////////////////////////////////////////////////////////////////////// - template::value> - struct pop_segments - { - typedef range_next next; - typedef push_segments push; - typedef typename push::type type; - - static type call(State const &state) - { - typename next::type rng(next::call(state.car)); - return push::call(rng, state.cdr); - } - }; - - template - struct pop_segments - { - typedef pop_segments pop; - typedef typename pop::type type; - - static type call(State const &state) - { - return pop::call(state.cdr); - } - }; - - template<> - struct pop_segments - { - typedef nil type; - - static type call(nil const &) - { - return nil(); - } - }; - } // namespace detail - - struct segmented_iterator_tag; - - //////////////////////////////////////////////////////////////////////////// - template + struct segmented_iterator_tag {}; + + // A segmented iterator is a stack of segment nodes. + // Note: push_front/pop_front create views. That should + // be good enough. + template struct segmented_iterator - : fusion::iterator_base > + : fusion::iterator_base > { + typedef forward_traversal_tag category; typedef segmented_iterator_tag fusion_tag; - typedef fusion::forward_traversal_tag category; - typedef Cons cons_type; - typedef typename Cons::car_type car_type; - typedef typename Cons::cdr_type cdr_type; - - explicit segmented_iterator(Cons const &c) - : cons_(c) + explicit segmented_iterator(Nodes const &ns) + : nodes(ns) {} - cons_type const &cons() const { return this->cons_; }; - car_type const &car() const { return this->cons_.car; }; - cdr_type const &cdr() const { return this->cons_.cdr; }; - - private: - Cons cons_; + typedef Nodes nodes_type; + nodes_type nodes; }; - /////////////////////////////////////////////////////////////////////////// - template - struct segmented_begin - { - typedef typename detail::push_segments push; - typedef segmented_iterator type; - - static type call(Sequence &seq) - { - return type(push::call(seq, nil())); - } - }; - - /////////////////////////////////////////////////////////////////////////// - template - struct segmented_end - { - typedef segmented_iterator type; - - static type call(Sequence &) - { - return type(nil()); - } - }; - - namespace extension - { - template<> - struct value_of_impl - { - template - struct apply - { - typedef typename result_of::begin::type begin; - typedef typename result_of::value_of::type type; - }; - }; - - template<> - struct deref_impl - { - template - struct apply - { - typedef typename result_of::begin::type begin; - typedef typename result_of::deref::type type; - - static type call(Iterator const &it) - { - return *fusion::begin(it.car()); - } - }; - }; - - // discards the old head, expands the right child of the new head - // and pushes the result to the head of the list. - - template<> - struct next_impl - { - template< - typename Iterator - , bool IsSegmentDone = detail::is_range_next_empty::value - > - struct apply - { - typedef typename Iterator::cdr_type cdr_type; - typedef detail::range_next next; - typedef segmented_iterator > type; - - static type call(Iterator const &it) - { - return type(fusion::make_cons(next::call(it.car()), it.cdr())); - } - }; - - template - struct apply // segment done, move to next segment - { - typedef typename Iterator::cdr_type cdr_type; - typedef typename detail::pop_segments pop; - typedef segmented_iterator type; - - static type call(Iterator const &it) - { - return type(pop::call(it.cdr())); - } - }; - }; - } -}} // namespace boost::fusion +}} #endif diff --git a/include/boost/fusion/view/ext_/segmented_iterator_range.hpp b/include/boost/fusion/view/ext_/segmented_iterator_range.hpp old mode 100755 new mode 100644 index 803e642b..209faee5 --- a/include/boost/fusion/view/ext_/segmented_iterator_range.hpp +++ b/include/boost/fusion/view/ext_/segmented_iterator_range.hpp @@ -1,537 +1,549 @@ /*============================================================================= - Copyright (c) 2006 Eric Niebler + Copyright (c) 2011 Eric Niebler - Use, modification and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#ifndef FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 -#define FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 +#if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED) +#define BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED -#include -#include -#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include +#include -namespace boost { namespace fusion +// Invariants: +// - Each segmented iterator has a stack +// - Each value in the stack is an iterator range +// - The range at the top of the stack points to values +// - All other ranges point to ranges +// - The front of each range in the stack (besides the +// topmost) is the range above it + +namespace boost { namespace fusion { namespace detail { - namespace detail + //auto make_segment_sequence_front(stack_begin) + //{ + // switch (size(stack_begin)) + // { + // case 1: + // return nil; + // case 2: + // // car(cdr(stack_begin)) is a range over values. + // assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin)))); + // return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin)))); + // default: + // // car(cdr(stack_begin)) is a range over segments. We replace the + // // front with a view that is restricted. + // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin)))); + // return segment_sequence( + // push_front( + // // The following could be a segment_sequence. It then gets wrapped + // // in a single_view, and push_front puts it in a join_view with the + // // following iterator_range. + // iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))), + // make_segment_sequence_front(cdr(stack_begin)))); + // } + //} + + template + struct make_segment_sequence_front { - //////////////////////////////////////////////////////////////////////////// - template - struct reverse_cons; + // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin)))); + BOOST_MPL_ASSERT(( + result_of::equal_to< + typename result_of::end< + typename remove_reference< + typename add_const< + typename result_of::segments< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::end_type + >)); - template - struct reverse_cons, State> - { - typedef reverse_cons > reverse; - typedef typename reverse::type type; - - static type call(cons const &cons, State const &state = State()) - { - return reverse::call(cons.cdr, fusion::make_cons(cons.car, state)); - } - }; - - template - struct reverse_cons - { - typedef State type; - - static State const &call(nil const &, State const &state = State()) - { - return state; - } - }; - - //////////////////////////////////////////////////////////////////////////// - // tags - struct full_view {}; - struct left_view {}; - struct right_view {}; - struct center_view {}; - - template - struct segmented_view_tag; - - //////////////////////////////////////////////////////////////////////////// - // a segmented view of that includes all elements either to the - // right or the left of a segmented iterator. - template - struct segmented_view - : sequence_base > - { - typedef segmented_view_tag fusion_tag; - typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef mpl::true_ is_view; - typedef forward_traversal_tag category; - - explicit segmented_view(Cons1 const &cons) - : cons(cons) - {} - - typedef Cons1 cons_type; - cons_type const &cons; - }; - - // a segmented view that contains all the elements in between - // two segmented iterators - template - struct segmented_view - : sequence_base > - { - typedef segmented_view_tag fusion_tag; - typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef mpl::true_ is_view; - typedef forward_traversal_tag category; - - segmented_view(Cons1 const &lcons, Cons2 const &rcons) - : left_cons(lcons) - , right_cons(rcons) - {} - - typedef Cons1 left_cons_type; - typedef Cons2 right_cons_type; - - left_cons_type const &left_cons; - right_cons_type const &right_cons; - }; - - //////////////////////////////////////////////////////////////////////////// - // Used to transform a sequence of segments. The first segment is - // bounded by RightCons, and the last segment is bounded by LeftCons - // and all the others are passed through unchanged. - template - struct segments_transform - { - explicit segments_transform(RightCons const &cons_) - : right_cons(cons_) - , left_cons(cons_) - {} - - segments_transform(RightCons const &right_cons_, LeftCons const &left_cons_) - : right_cons(right_cons_) - , left_cons(left_cons_) - {} - - template - struct result_; - - template - struct result_ - { - typedef segmented_view type; - }; - - template - struct result_ - { - typedef segmented_view type; - }; - - template - struct result_ - { - typedef Second type; - }; - - template - struct result; - - template - struct result - : result_< - typename remove_cv::type>::type - , typename remove_cv::type>::type - > - {}; - - template - segmented_view operator ()(right_view, Second &second) const - { - return segmented_view(this->right_cons); - } - - template - segmented_view operator ()(left_view, Second &second) const - { - return segmented_view(this->left_cons); - } - - template - Second &operator ()(full_view, Second &second) const - { - return second; - } - - private: - RightCons const &right_cons; - LeftCons const &left_cons; - }; - - } // namespace detail - - namespace extension - { - //////////////////////////////////////////////////////////////////////////// - template - struct is_segmented_impl > - { - template - struct apply - : mpl::true_ - {}; - }; - - //////////////////////////////////////////////////////////////////////////// - template<> - struct segments_impl > - { - template< - typename Sequence - , typename Cdr = typename Sequence::cons_type::cdr_type + typedef + iterator_range< + typename result_of::next< + typename Stack::cdr_type::car_type::begin_type + >::type, + typename result_of::end< + typename remove_reference< + typename add_const< + typename result_of::segments< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type + >::type + >::type + >::type > - struct apply - { - typedef typename Sequence::cons_type::car_type segmented_range; - typedef typename result_of::size::type size; - typedef typename mpl::prior::type size_minus_1; - typedef detail::segments_transform tfx; - typedef joint_view< - single_view const - , multiple_view const - > mask; - typedef transform_view type; + rest_type; - static type call(Sequence &seq) - { - return type( - mask( - make_single_view(detail::right_view()) - , make_multiple_view(detail::full_view()) - ) - , seq.cons.car - , tfx(seq.cons.cdr) - ); - } - }; + typedef + make_segment_sequence_front + recurse; - template - struct apply - { - typedef typename Sequence::cons_type::car_type segmented_range; - typedef typename segmented_range::iterator_type begin; - typedef typename segmented_range::sequence_non_ref_type sequence_type; - typedef typename result_of::end::type end; - typedef iterator_range range; - typedef single_view type; - - static type call(Sequence &seq) - { - return type(range(seq.cons.car.where_, fusion::end(seq.cons.car.sequence))); - } - }; - }; - - //////////////////////////////////////////////////////////////////////////// - template<> - struct segments_impl > - { - template< - typename Sequence - , typename Cdr = typename Sequence::cons_type::cdr_type + typedef + segment_sequence< + typename result_of::push_front< + rest_type const, + typename recurse::type + >::type > - struct apply - { - typedef typename Sequence::cons_type::car_type right_segmented_range; - typedef typename right_segmented_range::sequence_type sequence_type; - typedef typename right_segmented_range::iterator_type iterator_type; + type; - typedef iterator_range< - typename result_of::begin::type - , typename result_of::next::type - > segmented_range; - - typedef detail::segments_transform tfx; - typedef typename result_of::size::type size; - typedef typename mpl::prior::type size_minus_1; - typedef joint_view< - multiple_view const - , single_view const - > mask; - typedef transform_view type; - - static type call(Sequence &seq) - { - return type( - mask( - make_multiple_view(detail::full_view()) - , make_single_view(detail::left_view()) - ) - , segmented_range(fusion::begin(seq.cons.car.sequence), fusion::next(seq.cons.car.where_)) - , tfx(seq.cons.cdr) - ); - } - }; - - template - struct apply - { - typedef typename Sequence::cons_type::car_type segmented_range; - typedef typename segmented_range::sequence_non_ref_type sequence_type; - typedef typename result_of::begin::type begin; - typedef typename segmented_range::iterator_type end; - typedef iterator_range range; - typedef single_view type; - - static type call(Sequence &seq) - { - return type(range(fusion::begin(seq.cons.car.sequence), seq.cons.car.where_)); - } - }; - }; - - //////////////////////////////////////////////////////////////////////////// - template<> - struct segments_impl > + static type call(Stack stack) { - template - struct apply - { - typedef typename Sequence::right_cons_type right_cons_type; - typedef typename Sequence::left_cons_type left_cons_type; - typedef typename right_cons_type::car_type right_segmented_range; - typedef typename left_cons_type::car_type left_segmented_range; - - typedef iterator_range< - typename result_of::begin::type - , typename result_of::next::type>::type - > segmented_range; - - typedef typename mpl::minus< - typename result_of::size::type - , mpl::int_<2> - >::type size_minus_2; - - BOOST_MPL_ASSERT_RELATION(0, <=, size_minus_2::value); - - typedef detail::segments_transform< - typename left_cons_type::cdr_type - , typename right_cons_type::cdr_type - > tfx; - - typedef joint_view< - multiple_view const - , single_view const - > left_mask; - - typedef joint_view< - single_view const - , left_mask const - > mask; - - typedef transform_view type; - - static type call(Sequence &seq) - { - left_mask lmask( - make_multiple_view(detail::full_view()) - , make_single_view(detail::left_view()) - ); - return type( - mask(make_single_view(detail::right_view()), lmask) - , segmented_range(fusion::begin(seq.left_cons.car), fusion::next(fusion::begin(seq.right_cons.car))) - , tfx(seq.left_cons.cdr, seq.right_cons.cdr) - ); - } - }; - }; - } - - // specialize iterator_range for use with segmented iterators, so that - // it presents a segmented view of the range. - template - struct iterator_range; - - template - struct iterator_range, segmented_iterator > - : sequence_base, segmented_iterator > > - { - typedef typename convert_iterator >::type begin_type; - typedef typename convert_iterator >::type end_type; - typedef typename detail::reverse_cons::type begin_cons_type; - typedef typename detail::reverse_cons::type end_cons_type; - typedef iterator_range_tag fusion_tag; - typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef typename traits::category_of::type category; - typedef typename result_of::distance::type size; - typedef mpl::true_ is_view; - - iterator_range(segmented_iterator const& first_, segmented_iterator const& last_) - : first(convert_iterator >::call(first_)) - , last(convert_iterator >::call(last_)) - , first_cons(detail::reverse_cons::call(first_.cons())) - , last_cons(detail::reverse_cons::call(last_.cons())) - {} - - begin_type first; - end_type last; - - begin_cons_type first_cons; - end_cons_type last_cons; + //return segment_sequence( + // push_front( + // iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))), + // make_segment_sequence_front(cdr(stack_begin)))); + return type( + fusion::push_front( + rest_type(fusion::next(stack.cdr.car.first), fusion::end(fusion::segments(*stack.car.first))), + recurse::call(stack.cdr))); + } }; - namespace detail + template + struct make_segment_sequence_front { + // assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin)))); + BOOST_MPL_ASSERT(( + result_of::equal_to< + typename result_of::end< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::end_type + >)); - template - struct same_segment - : mpl::false_ - {}; - - template - struct same_segment, cons > - : mpl::and_< - traits::is_segmented - , is_same + typedef + iterator_range< + typename Stack::cdr_type::car_type::begin_type, + typename result_of::end< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type > - {}; + type; - //////////////////////////////////////////////////////////////////////////// - template - struct segments_gen; - - //////////////////////////////////////////////////////////////////////////// - template - struct segments_gen2 + static type call(Stack stack) { - typedef segments_gen gen; - typedef typename gen::type type; + // return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin)))); + return type(stack.cdr.car.first, fusion::end(*stack.car.first)); + } + }; - static type call(Cons1 const &cons1, Cons2 const &cons2) - { - return gen::call(cons1.cdr, cons2.cdr); - } - }; - - template - struct segments_gen2 - { - typedef segmented_view view; - typedef typename result_of::segments::type type; - - static type call(Cons1 const &cons1, Cons2 const &cons2) - { - view v(cons1, cons2); - return fusion::segments(v); - } - }; - - template - struct segments_gen2, cons, false> - { - typedef iterator_range< - typename Car1::iterator_type - , typename Car2::iterator_type - > range; - - typedef single_view type; - - static type call(cons const &cons1, cons const &cons2) - { - return type(range(cons1.car.where_, cons2.car.where_)); - } - }; - - //////////////////////////////////////////////////////////////////////////// - template - struct segments_gen - : segments_gen2::value> - {}; - - template - struct segments_gen, nil> - { - typedef segmented_view > view; - typedef typename result_of::segments::type type; - - static type call(cons const &cons, nil const &) - { - view v(cons); - return fusion::segments(v); - } - }; - - template<> - struct segments_gen - { - typedef nil type; - - static type call(nil const &, nil const &) - { - return nil(); - } - }; - } // namespace detail - - namespace extension + template + struct make_segment_sequence_front { - template - struct is_segmented_impl; - - // An iterator_range of segmented_iterators is segmented - template<> - struct is_segmented_impl + typedef nil type; + static type call(Stack const &) { - template - struct is_segmented_iterator : mpl::false_ {}; + return nil(); + } + }; - template - struct is_segmented_iterator > : mpl::true_ {}; + //auto make_segment_sequence_back(stack_end) + //{ + // switch (size(stack_end)) + // { + // case 1: + // return nil; + // case 2: + // // car(cdr(stack_back)) is a range over values. + // assert(end(front(car(stack_end))) == end(car(cdr(stack_end)))); + // return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end)))); + // default: + // // car(cdr(stack_begin)) is a range over segments. We replace the + // // back with a view that is restricted. + // assert(end(segments(front(car(stack_end)))) == end(car(cdr(stack_end)))); + // return segment_sequence( + // push_back( + // iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))), + // make_segment_sequence_back(cdr(stack_end)))); + // } + //} - template - struct apply - : mpl::and_< - is_segmented_iterator - , is_segmented_iterator - > - {}; - }; + template + struct make_segment_sequence_back + { + // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin)))); + BOOST_MPL_ASSERT(( + result_of::equal_to< + typename result_of::end< + typename remove_reference< + typename add_const< + typename result_of::segments< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::end_type + >)); + + typedef + iterator_range< + typename result_of::begin< + typename remove_reference< + typename add_const< + typename result_of::segments< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::begin_type + > + rest_type; + + typedef + make_segment_sequence_back + recurse; + + typedef + segment_sequence< + typename result_of::push_back< + rest_type const, + typename recurse::type + >::type + > + type; + + static type call(Stack stack) + { + // return segment_sequence( + // push_back( + // iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))), + // make_segment_sequence_back(cdr(stack_end)))); + return type( + fusion::push_back( + rest_type(fusion::begin(fusion::segments(*stack.car.first)), stack.cdr.car.first), + recurse::call(stack.cdr))); + } + }; + + template + struct make_segment_sequence_back + { + // assert(end(front(car(stack_end))) == end(car(cdr(stack_end)))); + BOOST_MPL_ASSERT(( + result_of::equal_to< + typename result_of::end< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::end_type + >)); + + typedef + iterator_range< + typename result_of::begin< + typename remove_reference< + typename result_of::deref< + typename Stack::car_type::begin_type + >::type + >::type + >::type, + typename Stack::cdr_type::car_type::begin_type + > + type; + + static type call(Stack stack) + { + // return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end)))); + return type(fusion::begin(*stack.car.first), stack.cdr.car.first); + } + }; + + template + struct make_segment_sequence_back + { + typedef nil type; + static type call(Stack const &) + { + return nil(); + } + }; + + //auto make_segmented_range_reduce(stack_begin, stack_end) + //{ + // if (size(stack_begin) == 1 && size(stack_end) == 1) + // { + // return segment_sequence( + // single_view( + // iterator_range(begin(car(stack_begin)), begin(car(stack_end))))); + // } + // else + // { + // // We are in the case where both begin_stack and/or end_stack have + // // more than one element. Throw away any part of the tree where + // // begin and end refer to the same segment. + // if (begin(car(stack_begin)) == begin(car(stack_end))) + // { + // return make_segmented_range_reduce(cdr(stack_begin), cdr(stack_end)); + // } + // else + // { + // // We are in the case where begin_stack and end_stack (a) have + // // more than one element each, and (b) they point to different + // // segments. We must construct a segmented sequence. + // return segment_sequence( + // push_back( + // push_front( + // iterator_range( + // fusion::next(begin(car(stack_begin))), + // begin(car(stack_end))), // a range of (possibly segmented) ranges. + // make_segment_sequence_front(stack_begin)), // should be a (possibly segmented) range. + // make_segment_sequence_back(stack_end))); // should be a (possibly segmented) range. + // } + // } + //} + + template< + typename StackBegin, + typename StackEnd, + int StackBeginSize = StackBegin::size::value, + int StackEndSize = StackEnd::size::value> + struct make_segmented_range_reduce; + + template< + typename StackBegin, + typename StackEnd, + bool SameSegment = + result_of::equal_to< + typename StackBegin::car_type::begin_type, + typename StackEnd::car_type::begin_type + >::type::value> + struct make_segmented_range_reduce2 + { + typedef + iterator_range< + typename result_of::next< + typename StackBegin::car_type::begin_type + >::type, + typename StackEnd::car_type::begin_type + > + rest_type; + + typedef + segment_sequence< + typename result_of::push_back< + typename result_of::push_front< + rest_type const, + typename make_segment_sequence_front::type + >::type const, + typename make_segment_sequence_back::type + >::type + > + type; + + static type call(StackBegin stack_begin, StackEnd stack_end) + { + //return segment_sequence( + // push_back( + // push_front( + // iterator_range( + // fusion::next(begin(car(stack_begin))), + // begin(car(stack_end))), // a range of (possibly segmented) ranges. + // make_segment_sequence_front(stack_begin)), // should be a (possibly segmented) range. + // make_segment_sequence_back(stack_end))); // should be a (possibly segmented) range. + return type( + fusion::push_back( + fusion::push_front( + rest_type(fusion::next(stack_begin.car.first), stack_end.car.first), + make_segment_sequence_front::call(stack_begin)), + make_segment_sequence_back::call(stack_end))); + } + }; + + template + struct make_segmented_range_reduce2 + { + typedef + make_segmented_range_reduce< + typename StackBegin::cdr_type, + typename StackEnd::cdr_type + > + impl; + + typedef + typename impl::type + type; + + static type call(StackBegin stack_begin, StackEnd stack_end) + { + return impl::call(stack_begin.cdr, stack_end.cdr); + } + }; + + template + struct make_segmented_range_reduce + : make_segmented_range_reduce2 + {}; + + template + struct make_segmented_range_reduce + { + typedef + iterator_range< + typename StackBegin::car_type::begin_type, + typename StackEnd::car_type::begin_type + > + range_type; + + typedef + single_view + segment_type; + + typedef + segment_sequence + type; + + static type call(StackBegin stack_begin, StackEnd stack_end) + { + //return segment_sequence( + // single_view( + // iterator_range(begin(car(stack_begin)), begin(car(stack_end))))); + return type(segment_type(range_type(stack_begin.car.first, stack_end.car.first))); + } + }; + + //auto make_segmented_range(begin, end) + //{ + // return make_segmented_range_reduce(reverse(begin.nodes), reverse(end.nodes)); + //} + + template + struct make_segmented_range + { + typedef reverse_cons reverse_begin_cons; + typedef reverse_cons reverse_end_cons; + + typedef + make_segmented_range_reduce< + typename reverse_begin_cons::type, + typename reverse_end_cons::type + > + impl; + + typedef typename impl::type type; + + static type call(Begin const & begin, End const & end) + { + return impl::call( + reverse_begin_cons::call(begin.nodes), + reverse_end_cons::call(end.nodes)); + } + }; + +}}} + +namespace boost { namespace fusion { namespace extension +{ + template + struct is_segmented_impl; + + // An iterator_range of segmented_iterators is segmented + template<> + struct is_segmented_impl + { + template + struct is_segmented_iterator + : is_same< + segmented_iterator_tag, + typename traits::tag_of::type> + {}; template - struct segments_impl; - - template<> - struct segments_impl + struct apply + : is_segmented_iterator { - template - struct apply - { - typedef typename Sequence::begin_cons_type begin_cons; - typedef typename Sequence::end_cons_type end_cons; - - typedef detail::segments_gen gen; - typedef typename gen::type type; - - static type call(Sequence &sequence) - { - return gen::call(sequence.first_cons, sequence.last_cons); - } - }; + BOOST_MPL_ASSERT_RELATION( + is_segmented_iterator::value, + ==, + is_segmented_iterator::value); }; - } + }; -}} + template + struct segments_impl; + + template<> + struct segments_impl + { + template + struct apply + { + typedef + detail::make_segmented_range< + typename Sequence::begin_type, + typename Sequence::end_type + > + impl; + + BOOST_MPL_ASSERT((traits::is_segmented)); + + typedef + typename result_of::segments::type + type; + + static type call(Sequence & seq) + { + return fusion::segments(impl::call(seq.first, seq.last)); + } + }; + }; + + // TODO: remove invocation of distance in iterator_range. + // TODO: default implementation of begin, end, and size + // should check if the sequence is segmented and to + // the right thing. + +}}} #endif diff --git a/include/boost/fusion/view/iterator_range/detail/size_impl.hpp b/include/boost/fusion/view/iterator_range/detail/size_impl.hpp new file mode 100644 index 00000000..90951b2f --- /dev/null +++ b/include/boost/fusion/view/iterator_range/detail/size_impl.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_FUSION_ITERATOR_RANGE_SIZE_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_ITERATOR_RANGE_SIZE_IMPL_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply + : result_of::distance< + typename Seq::begin_type, + typename Seq::end_type + > + {}; + }; + } +}} + +#endif + diff --git a/include/boost/fusion/view/iterator_range/iterator_range.hpp b/include/boost/fusion/view/iterator_range/iterator_range.hpp index 4d16ca6c..5e000b72 100644 --- a/include/boost/fusion/view/iterator_range/iterator_range.hpp +++ b/include/boost/fusion/view/iterator_range/iterator_range.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ namespace boost { namespace fusion typedef typename convert_iterator::type end_type; typedef iterator_range_tag fusion_tag; typedef fusion_sequence_tag tag; // this gets picked up by MPL - typedef typename result_of::distance::type size; typedef mpl::true_ is_view; typedef typename traits::category_of::type category; diff --git a/test/Jamfile b/test/Jamfile index fe8829e6..7a7e7186 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -157,9 +157,15 @@ import testing ; run algorithm/ext_/for_each_s.cpp ; explicit for_each_s ; + run algorithm/ext_/find_s.cpp ; + explicit find_s ; + run algorithm/ext_/find_if_s.cpp ; explicit find_if_s ; + run algorithm/ext_/fold_s.cpp ; + explicit fold_s ; + run sequence/ext_/iterator_range_s.cpp ; explicit iterator_range_s ; } diff --git a/test/algorithm/ext_/find_if_s.cpp b/test/algorithm/ext_/find_if_s.cpp old mode 100755 new mode 100644 index 7f33ea45..805fd599 --- a/test/algorithm/ext_/find_if_s.cpp +++ b/test/algorithm/ext_/find_if_s.cpp @@ -1,29 +1,18 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #include #include -#include -#include #include #include #include -#include -#include -#include +#include #include -struct X -{ - operator int() const - { - return 12345; - } -}; - template void process_tree(Tree const &tree) @@ -48,61 +37,21 @@ int main() { using namespace boost::fusion; - - { - using boost::is_same; - using boost::mpl::_; - - typedef vector vector_type; - vector_type v(12345, 'x', 678910, 3.36); - - std::cout << *find_if_s >(v) << std::endl; - BOOST_TEST((*find_if_s >(v) == 'x')); - - std::cout << *find_if_s >(v) << std::endl; - BOOST_TEST((*find_if_s >(v) == 12345)); - - std::cout << *find_if_s >(v) << std::endl; - BOOST_TEST((*find_if_s >(v) == 3.36)); - } - - { - using boost::mpl::vector; - using boost::is_same; - using boost::mpl::_; - - typedef vector mpl_vec; - BOOST_TEST((*find_if_s >(mpl_vec()) == 12345)); - } - - { - using boost::mpl::vector_c; - using boost::mpl::less; - using boost::mpl::int_; - using boost::is_same; - using boost::mpl::_; - - typedef vector_c mpl_vec; - BOOST_TEST((*find_if_s > >(mpl_vec()) == 1)); - } - - { - process_tree( - make_tree( - make_vector(double(0),'B') - , make_tree( - make_vector(1,2,long(3)) - , make_tree(make_vector('a','b','c')) - , make_tree(make_vector(short('d'),'e','f')) - ) - , make_tree( - make_vector(4,5,6) - , make_tree(make_vector(float(1),'h','i')) - , make_tree(make_vector('j','k','l')) - ) + process_tree( + make_tree( + make_vector(double(0),'B') + , make_tree( + make_vector(1,2,long(3)) + , make_tree(make_vector('a','b','c')) + , make_tree(make_vector(short('d'),'e','f')) ) - ); - } + , make_tree( + make_vector(4,5,6) + , make_tree(make_vector(float(1),'h','i')) + , make_tree(make_vector('j','k','l')) + ) + ) + ); return boost::report_errors(); } diff --git a/test/algorithm/ext_/find_s.cpp b/test/algorithm/ext_/find_s.cpp new file mode 100644 index 00000000..be5d332e --- /dev/null +++ b/test/algorithm/ext_/find_s.cpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#include +#include +#include +#include +#include + +template +void +process_tree(Tree const &tree) +{ + using namespace boost; + + typedef typename fusion::result_of::find_s::type short_iter; + typedef typename fusion::result_of::find_s::type float_iter; + + // find_if_s of a segmented data structure returns generic + // segmented iterators + short_iter si = fusion::find_s(tree); + float_iter fi = fusion::find_s(tree); + + // they behave like ordinary Fusion iterators ... + BOOST_TEST((*si == short('d'))); + BOOST_TEST((*fi == float(1))); +} + +int +main() +{ + using namespace boost::fusion; + process_tree( + make_tree( + make_vector(double(0),'B') + , make_tree( + make_vector(1,2,long(3)) + , make_tree(make_vector('a','b','c')) + , make_tree(make_vector(short('d'),'e','f')) + ) + , make_tree( + make_vector(4,5,6) + , make_tree(make_vector(float(1),'h','i')) + , make_tree(make_vector('j','k','l')) + ) + ) + ); + + return boost::report_errors(); +} + diff --git a/test/algorithm/ext_/fold_s.cpp b/test/algorithm/ext_/fold_s.cpp new file mode 100644 index 00000000..f774c2a4 --- /dev/null +++ b/test/algorithm/ext_/fold_s.cpp @@ -0,0 +1,62 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2011 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#include +#include +#include +#include +#include +#include +#include + +struct write_string +{ + typedef std::ostream* result_type; + + template + std::ostream* operator()(std::ostream* sout, T const& t) const + { + return &(*sout << t << " "); + } +}; + +template +void +process_tree(Tree const &tree) +{ + using namespace boost; + + std::stringstream str; + fusion::fold_s(tree, &str, write_string()); + std::string res = str.str(); + + BOOST_TEST_EQ(res, "a b c 1 2 3 100 e f 0 B 1 h i 4 5 6 j k l "); +} + +int +main() +{ + using namespace boost::fusion; + process_tree( + make_tree( + make_vector(double(0),'B') + , make_tree( + make_vector(1,2,long(3)) + , make_tree(make_vector('a','b','c')) + , make_tree(make_vector(short('d'),'e','f')) + ) + , make_tree( + make_vector(4,5,6) + , make_tree(make_vector(float(1),'h','i')) + , make_tree(make_vector('j','k','l')) + ) + ) + ); + + return boost::report_errors(); +} + diff --git a/test/algorithm/ext_/for_each_s.cpp b/test/algorithm/ext_/for_each_s.cpp old mode 100755 new mode 100644 index 63ffed2c..9467a101 --- a/test/algorithm/ext_/for_each_s.cpp +++ b/test/algorithm/ext_/for_each_s.cpp @@ -1,15 +1,13 @@ /*============================================================================= - Copyright (c) 2001-2006 Joel de Guzman, Eric Niebler + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #include #include -#include -#include #include -#include #include #include @@ -22,44 +20,13 @@ struct print } }; -struct increment -{ - template - void operator()(T& v) const - { - ++v; - } -}; - int main() { using namespace boost::fusion; - using boost::mpl::vector_c; - namespace fusion = boost::fusion; { - typedef vector vector_type; - vector_type v(1, 'x', 3.3, "Ruby"); - for_each_s(v, print()); - std::cout << std::endl; - } - - { - typedef vector vector_type; - vector_type v(1, 'x', 3.3, "Ruby"); - for_each_s(v, increment()); - std::cout << v << std::endl; - } - - { - typedef vector_c mpl_vec; - fusion::for_each_s(mpl_vec(), print()); - std::cout << std::endl; - } - - { - fusion::for_each_s( + for_each_s( make_tree( make_vector(double(0),'B') , make_tree( diff --git a/test/sequence/ext_/iterator_range_s.cpp b/test/sequence/ext_/iterator_range_s.cpp old mode 100755 new mode 100644 index 02a49ad4..4aea3ae5 --- a/test/sequence/ext_/iterator_range_s.cpp +++ b/test/sequence/ext_/iterator_range_s.cpp @@ -1,5 +1,6 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2011 Eric Niebler Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)