From 82d8d2630864c89d672cf274e4dbc5d5ea20952d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 2 Apr 2010 19:48:39 +0200 Subject: [PATCH] extend the map iterator adapter to work on STL ranges --- src/lib/iter-adapter-stl.hpp | 216 ++++++++++++++++++++-------- tests/lib/iter-adapter-stl-test.cpp | 2 + 2 files changed, 161 insertions(+), 57 deletions(-) diff --git a/src/lib/iter-adapter-stl.hpp b/src/lib/iter-adapter-stl.hpp index 75ad75682..63ec756cb 100644 --- a/src/lib/iter-adapter-stl.hpp +++ b/src/lib/iter-adapter-stl.hpp @@ -49,36 +49,10 @@ namespace lib { namespace iter_stl { - /** - * helper baseclass to simplify - * defining customised wrapped STL iterators + * Helper to filter repeated values + * from a wrapped iterator (both STL or Lumiera) */ - template - class WrappedStlIter - { - IT i_; - - public: - typedef typename IT::value_type value_type; - typedef typename IT::reference reference; - typedef typename IT::pointer pointer; - - - WrappedStlIter() : i_() { } - WrappedStlIter(IT const& i) : i_(i) { } - - IT const& get() const { return i_; } - pointer operator->() const { return i_; } - reference operator*() const { return *i_; } - - WrappedStlIter& operator++() { ++i_; return *this; } - - friend bool operator== (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ == i2.i_; } - friend bool operator!= (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ != i2.i_; } - }; - - template class DistinctIter : public lib::BoolCheckable > @@ -118,6 +92,95 @@ namespace iter_stl { + /** + * helper baseclass to simplify + * defining customised wrapped STL iterators + */ + template + struct WrappedStlIter : DEF + { + typedef typename DEF::Iter Iter; + typedef typename DEF::reference reference; + typedef typename DEF::pointer pointer; + + + WrappedStlIter() : i_() { } + WrappedStlIter(Iter const& i) : i_(i) { } + + pointer operator->() const { return DEF::get(i_); } + reference operator*() const { return *(DEF::get(i_)); } + + WrappedStlIter& operator++() { ++i_; return *this; } + + friend bool operator== (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ == i2.i_; } + friend bool operator!= (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ != i2.i_; } + + private: + mutable Iter i_; + }; + + + /* -- customisations for building concrete wrappers -- */ + + /** + * Wrapped-Iter-Policy: forwarding directly + * with typing retained unaltered. + */ + template + struct Wrapped_Identity + { + typedef IT Iter; + typedef typename IT::value_type value_type; + typedef typename IT::reference reference; + typedef typename IT::pointer pointer; + + static Iter get (Iter& it) { return & (*it); } + }; + + /** + * Wrapped-Iter-Policy: picking the key part + * of a pair iterator (map or multimap). + */ + template + struct Wrapped_PickKey + { + typedef IT Iter; + typedef typename IT::value_type::first_type value_type; + typedef value_type & reference; + typedef value_type * pointer; + + static pointer get (Iter& it) { return & (it->first); } + }; + + /** + * Wrapped-Iter-Policy: picking the key part + * of a pair iterator (map or multimap). + */ + template + struct Wrapped_PickVal + { + typedef IT Iter; + typedef typename IT::value_type::second_type value_type; + typedef value_type & reference; + typedef value_type * pointer; + + static pointer get (Iter& it) { return & (it->second); } + }; + + template + struct Wrapped_PickConstVal + { + typedef IT Iter; + typedef typename IT::value_type::second_type value_type; + typedef value_type const& reference; + typedef value_type const* pointer; + + static pointer get (Iter& it) { return & (it->second); } + }; + + + + namespace { // traits and helpers... @@ -138,6 +201,22 @@ namespace iter_stl { typedef typename MAP::const_iterator Itr; }; + /** helper to access the parts of the pair values correctly...*/ + template + struct _MapSubSelector + { + typedef WrappedStlIter< Wrapped_PickKey > PickKey; + typedef WrappedStlIter< Wrapped_PickVal > PickVal; + }; + + /** especially for const iterators we need to use \c const& and \c const* */ + template + struct _MapSubSelector + { + typedef WrappedStlIter< Wrapped_PickKey > PickKey; // Key is always const for maps + typedef WrappedStlIter< Wrapped_PickConstVal > PickVal; + }; + template @@ -147,38 +226,33 @@ namespace iter_stl { typedef typename _MapTypeSelector::Val ValType; typedef typename _MapTypeSelector::Itr EntryIter; - typedef WrappedStlIter WrapI; + typedef typename EntryIter::reference DetectConst; + typedef typename _MapSubSelector::PickKey PickKeyIter; + typedef typename _MapSubSelector::PickVal PickValIter; - struct PickKeyIter : WrapI - { - typedef KeyType value_type; - typedef KeyType& reference; - typedef KeyType* pointer; - - PickKeyIter () : WrapI() {} - PickKeyIter (EntryIter const& iter) : WrapI(iter) {} - - pointer operator->() const { return &(WrapI::get()->first); } - reference operator* () const { return (WrapI::get()->first); } - }; + typedef RangeIter KeyIter; + typedef RangeIter ValIter; - struct PickValIter : WrapI - { - typedef ValType value_type; - typedef ValType& reference; - typedef ValType* pointer; - - PickValIter () : WrapI() {} - PickValIter (EntryIter const& iter) : WrapI(iter) {} - - pointer operator->() const { return &(WrapI::get()->second); } - reference operator* () const { return (WrapI::get()->second); } - }; + typedef DistinctIter DistinctKeys; + }; + + + template + struct _MapIterT + { + typedef IT EntryIter; + + typedef typename EntryIter::value_type::first_type KeyType; + typedef typename EntryIter::value_type::second_type ValType; + + typedef typename EntryIter::reference DetectConst; + typedef typename _MapSubSelector::PickKey PickKeyIter; + typedef typename _MapSubSelector::PickVal PickValIter; - typedef RangeIter KeyIter; - typedef RangeIter ValIter; - - typedef DistinctIter DistinctKeys; + typedef RangeIter KeyIter; + typedef RangeIter ValIter; + + typedef DistinctIter DistinctKeys; }; @@ -218,6 +292,20 @@ namespace iter_stl { } + /** @return Lumiera Forward Iterator extracting the keys + * from a given range of (key,value) pairs + */ + template + inline typename _MapIterT::KeyIter + eachKey (IT const& begin, IT const& end) + { + typedef typename _MapIterT::KeyIter Range; + typedef typename _MapIterT::PickKeyIter PickKey; + + return Range (PickKey (begin), PickKey (end)); + } + + /** @return Lumiera Forward Iterator to yield * each value within a map/multimap */ @@ -232,6 +320,20 @@ namespace iter_stl { } + /** @return Lumiera Forward Iterator extracting the values + * from a given range of (key,value) pairs + */ + template + inline typename _MapIterT::ValIter + eachVal (IT const& begin, IT const& end) + { + typedef typename _MapIterT::ValIter Range; + typedef typename _MapIterT::PickValIter PickVal; + + return Range (PickVal (begin), PickVal (end)); + } + + /** build a Lumiera Forward Iterator to suppress * any repetitions in the given sequence. */ diff --git a/tests/lib/iter-adapter-stl-test.cpp b/tests/lib/iter-adapter-stl-test.cpp index dfe32a3c4..c72dfbcfb 100644 --- a/tests/lib/iter-adapter-stl-test.cpp +++ b/tests/lib/iter-adapter-stl-test.cpp @@ -113,7 +113,9 @@ namespace test{ PRINT_FUNC (iterateMapKeyVal, MAP); TEST_ITER (iter::eachKey, (map)); + TEST_ITER (iter::eachKey, (map.begin(), map.end())); TEST_ITER (iter::eachVal, (map)); + TEST_ITER (iter::eachVal, (map.begin(), map.end())); TEST_ITER (iter::eachDistinctKey, (map)); }