diff --git a/src/lib/iter-adapter-stl.hpp b/src/lib/iter-adapter-stl.hpp index e2565e550..86e23cb70 100644 --- a/src/lib/iter-adapter-stl.hpp +++ b/src/lib/iter-adapter-stl.hpp @@ -82,6 +82,44 @@ namespace iter_stl { }; + template + class DistinctIter + : public lib::BoolCheckable > + { + public: + typedef typename IT::value_type value_type; + typedef typename IT::reference reference; + typedef typename IT::pointer pointer; + + private: + IT i_; + pointer prev_; + + void memorise() { if (i_) prev_ = &(*i_); } + + public: + DistinctIter() : i_(), prev_() { } + DistinctIter(IT const& i) : i_(i),prev_() { memorise(); } + + pointer operator->() const { return i_; } + reference operator*() const { return *i_; } + bool isValid() const { return i_; } + + + DistinctIter& + operator++() + { + do ++i_; + while (i_ && prev_ && *prev_ == *i_ ); + memorise(); + return *this; + } + + friend bool operator== (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ == i2.i_; } + friend bool operator!= (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ != i2.i_; } + }; + + namespace { // traits and helpers... template @@ -117,8 +155,8 @@ namespace iter_stl { typedef KeyType& reference; typedef KeyType* pointer; - PickKeyIter () : WrapI() {} - PickKeyIter (EntryIter iter) : WrapI(iter) {} + PickKeyIter () : WrapI() {} + PickKeyIter (EntryIter const& iter) : WrapI(iter) {} pointer operator->() const { return &(WrapI::get()->first); } reference operator* () const { return (WrapI::get()->first); } @@ -130,8 +168,8 @@ namespace iter_stl { typedef ValType& reference; typedef ValType* pointer; - PickValIter () : WrapI() {} - PickValIter (EntryIter iter) : WrapI(iter) {} + PickValIter () : WrapI() {} + PickValIter (EntryIter const& iter) : WrapI(iter) {} pointer operator->() const { return &(WrapI::get()->second); } reference operator* () const { return (WrapI::get()->second); } @@ -140,6 +178,24 @@ namespace iter_stl { typedef RangeIter KeyIter; typedef RangeIter ValIter; }; + + + + template + struct _SeqT + { + typedef typename SEQ::iterator Iter; + typedef RangeIter Range; + typedef DistinctIter DistinctVals; + }; + + template + struct _SeqT + { + typedef typename SEQ::const_iterator Iter; + typedef RangeIter Range; + typedef DistinctIter DistinctVals; + }; } @@ -173,6 +229,20 @@ namespace iter_stl { } + /** build a Lumiera Forward Iterator to suppress + * any repetitions in the given sequence. + */ + template + inline typename _SeqT::DistinctVals + eachDistinct (SEQ& seq) + { + typedef typename _SeqT::Range Range; + typedef typename _SeqT::DistinctVals DistinctValues; + + return DistinctValues (Range (seq.begin(), seq.end())); + } + + /** */ template diff --git a/tests/lib/iter-adapter-stl-test.cpp b/tests/lib/iter-adapter-stl-test.cpp index 87d509a88..a2079644a 100644 --- a/tests/lib/iter-adapter-stl-test.cpp +++ b/tests/lib/iter-adapter-stl-test.cpp @@ -93,6 +93,7 @@ namespace test{ { if (0 < arg.size()) NUM_ELMS = lexical_cast (arg[0]); + checkDistinctValIter(); iterateMapKeyVal (getTestMap_int (NUM_ELMS)); } @@ -107,8 +108,34 @@ namespace test{ TEST_ITER (iter::eachVal, (map)); TEST_ITER (iter::eachDistinctKey, (map)); } - + + void + checkDistinctValIter() + { + PRINT_FUNC (filter-distinct-values, VecI); + + VecI vec; + TEST_ITER(iter::eachDistinct, (vec)); + + vec.push_back (1); + vec.push_back (1); + vec.push_back (1); + TEST_ITER(iter::eachDistinct, (vec)); + + vec.push_back (2); + vec.push_back (3); + vec.push_back (3); + vec.push_back (1); + TEST_ITER(iter::eachDistinct, (vec)); + + vec.push_back (1); + vec.push_back (1); + vec.push_back (1); + vec.push_back (1); + vec.push_back (1); + TEST_ITER(iter::eachDistinct, (vec)); + } }; LAUNCHER (IterAdapterSTL_test, "unit common");