From f1da55c1e9c5ef9bccd8bc674e04478871b0bc59 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 13 Nov 2009 02:52:34 +0000 Subject: [PATCH] avoid iterator invalidation in segmented_range, fixes #3583 [SVN r57622] --- .../fusion/view/ext_/segmented_iterator.hpp | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/include/boost/fusion/view/ext_/segmented_iterator.hpp b/include/boost/fusion/view/ext_/segmented_iterator.hpp index b28182a4..79bc707e 100644 --- a/include/boost/fusion/view/ext_/segmented_iterator.hpp +++ b/include/boost/fusion/view/ext_/segmented_iterator.hpp @@ -9,8 +9,10 @@ #define FUSION_SEGMENTED_ITERATOR_EAN_05032006_1027 #include +#include #include #include +#include #include #include #include @@ -20,6 +22,7 @@ #include #include // for nil #include +#include #include #include #include @@ -59,16 +62,15 @@ namespace boost { namespace fusion struct segmented_range_tag; //////////////////////////////////////////////////////////////////////////// - template + template struct segmented_range - : sequence_base > + : 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; - typedef Iterator iterator_type; // If this is a range of segments, skip over the empty ones typedef typename mpl::if_< @@ -83,20 +85,34 @@ namespace boost { namespace fusion , 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_)) - , where_(fusion::begin(sequence)) {} - segmented_range(sequence_type sequence_, iterator_type const &wh) + segmented_range(sequence_type sequence_, int) : sequence(sequence_) - , where_(wh) {} + iterator_type where_() const + { + return fusion::advance( + fusion::begin(const_cast(this->sequence)) + ); + } + sequence_type sequence; - iterator_type where_; + + private: + segmented_range &operator =(segmented_range const &); }; } @@ -148,7 +164,7 @@ namespace boost { namespace fusion typedef typename Sequence::iterator_type type; static type call(Sequence &seq) { - return seq.where_; + return seq.where_(); } }; }; @@ -176,15 +192,15 @@ namespace boost { namespace fusion template struct range_next; - template - struct range_next > + template + struct range_next > { - typedef typename result_of::next::type iterator_type; - typedef segmented_range type; + typedef typename mpl::next::type index_type; + typedef segmented_range type; - static type call(segmented_range const &rng) + static type call(segmented_range const &rng) { - return type(rng.sequence, fusion::next(rng.where_)); + return type(rng.sequence, 0); } }; @@ -205,8 +221,7 @@ namespace boost { namespace fusion { typedef typename result_of::segments::type segments; typedef typename remove_reference::type sequence; - typedef typename result_of::begin >::type begin; - typedef segmented_range type; + typedef segmented_range, true> type; static type call(Sequence &seq) { @@ -219,8 +234,7 @@ namespace boost { namespace fusion struct as_segmented_range { typedef typename remove_reference::type sequence; - typedef typename result_of::begin::type begin; - typedef segmented_range type; + typedef segmented_range, false> type; static type call(Sequence &seq) { @@ -228,10 +242,10 @@ namespace boost { namespace fusion } }; - template - struct as_segmented_range, IsSegmented> + template + struct as_segmented_range, IsSegmented> { - typedef segmented_range type; + typedef segmented_range type; static type &call(type &seq) { return seq;