| /* Copyright 2003-2008 Joaquin M Lopez Munoz. |
| * 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) |
| * |
| * See http://www.boost.org/libs/multi_index for library home page. |
| */ |
| |
| #ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP |
| #define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP |
| |
| #if defined(_MSC_VER)&&(_MSC_VER>=1200) |
| #pragma once |
| #endif |
| |
| #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
| #include <boost/mpl/apply.hpp> |
| #include <boost/multi_index/detail/prevent_eti.hpp> |
| #include <boost/operators.hpp> |
| |
| namespace boost{ |
| |
| namespace multi_index{ |
| |
| namespace detail{ |
| |
| /* Poor man's version of boost::iterator_adaptor. Used instead of the |
| * original as compile times for the latter are significantly higher. |
| * The interface is not replicated exactly, only to the extent necessary |
| * for internal consumption. |
| */ |
| |
| /* NB. The purpose of the (non-inclass) global operators ==, < and - defined |
| * above is to partially alleviate a problem of MSVC++ 6.0 by * which |
| * friend-injected operators on T are not visible if T is instantiated only |
| * in template code where T is a dependent type. |
| */ |
| |
| class iter_adaptor_access |
| { |
| public: |
| template<class Class> |
| static typename Class::reference dereference(const Class& x) |
| { |
| return x.dereference(); |
| } |
| |
| template<class Class> |
| static bool equal(const Class& x,const Class& y) |
| { |
| return x.equal(y); |
| } |
| |
| template<class Class> |
| static void increment(Class& x) |
| { |
| x.increment(); |
| } |
| |
| template<class Class> |
| static void decrement(Class& x) |
| { |
| x.decrement(); |
| } |
| |
| template<class Class> |
| static void advance(Class& x,typename Class::difference_type n) |
| { |
| x.advance(n); |
| } |
| |
| template<class Class> |
| static typename Class::difference_type distance_to( |
| const Class& x,const Class& y) |
| { |
| return x.distance_to(y); |
| } |
| }; |
| |
| template<typename Category> |
| struct iter_adaptor_selector; |
| |
| template<class Derived,class Base> |
| class forward_iter_adaptor_base: |
| public forward_iterator_helper< |
| Derived, |
| typename Base::value_type, |
| typename Base::difference_type, |
| typename Base::pointer, |
| typename Base::reference> |
| { |
| public: |
| typedef typename Base::reference reference; |
| |
| reference operator*()const |
| { |
| return iter_adaptor_access::dereference(final()); |
| } |
| |
| friend bool operator==(const Derived& x,const Derived& y) |
| { |
| return iter_adaptor_access::equal(x,y); |
| } |
| |
| Derived& operator++() |
| { |
| iter_adaptor_access::increment(final()); |
| return final(); |
| } |
| |
| private: |
| Derived& final(){return *static_cast<Derived*>(this);} |
| const Derived& final()const{return *static_cast<const Derived*>(this);} |
| }; |
| |
| template<class Derived,class Base> |
| bool operator==( |
| const forward_iter_adaptor_base<Derived,Base>& x, |
| const forward_iter_adaptor_base<Derived,Base>& y) |
| { |
| return iter_adaptor_access::equal( |
| static_cast<const Derived&>(x),static_cast<const Derived&>(y)); |
| } |
| |
| template<> |
| struct iter_adaptor_selector<std::forward_iterator_tag> |
| { |
| template<class Derived,class Base> |
| struct apply |
| { |
| typedef forward_iter_adaptor_base<Derived,Base> type; |
| }; |
| }; |
| |
| template<class Derived,class Base> |
| class bidirectional_iter_adaptor_base: |
| public bidirectional_iterator_helper< |
| Derived, |
| typename Base::value_type, |
| typename Base::difference_type, |
| typename Base::pointer, |
| typename Base::reference> |
| { |
| public: |
| typedef typename Base::reference reference; |
| |
| reference operator*()const |
| { |
| return iter_adaptor_access::dereference(final()); |
| } |
| |
| friend bool operator==(const Derived& x,const Derived& y) |
| { |
| return iter_adaptor_access::equal(x,y); |
| } |
| |
| Derived& operator++() |
| { |
| iter_adaptor_access::increment(final()); |
| return final(); |
| } |
| |
| Derived& operator--() |
| { |
| iter_adaptor_access::decrement(final()); |
| return final(); |
| } |
| |
| private: |
| Derived& final(){return *static_cast<Derived*>(this);} |
| const Derived& final()const{return *static_cast<const Derived*>(this);} |
| }; |
| |
| template<class Derived,class Base> |
| bool operator==( |
| const bidirectional_iter_adaptor_base<Derived,Base>& x, |
| const bidirectional_iter_adaptor_base<Derived,Base>& y) |
| { |
| return iter_adaptor_access::equal( |
| static_cast<const Derived&>(x),static_cast<const Derived&>(y)); |
| } |
| |
| template<> |
| struct iter_adaptor_selector<std::bidirectional_iterator_tag> |
| { |
| template<class Derived,class Base> |
| struct apply |
| { |
| typedef bidirectional_iter_adaptor_base<Derived,Base> type; |
| }; |
| }; |
| |
| template<class Derived,class Base> |
| class random_access_iter_adaptor_base: |
| public random_access_iterator_helper< |
| Derived, |
| typename Base::value_type, |
| typename Base::difference_type, |
| typename Base::pointer, |
| typename Base::reference> |
| { |
| public: |
| typedef typename Base::reference reference; |
| typedef typename Base::difference_type difference_type; |
| |
| reference operator*()const |
| { |
| return iter_adaptor_access::dereference(final()); |
| } |
| |
| friend bool operator==(const Derived& x,const Derived& y) |
| { |
| return iter_adaptor_access::equal(x,y); |
| } |
| |
| friend bool operator<(const Derived& x,const Derived& y) |
| { |
| return iter_adaptor_access::distance_to(x,y)>0; |
| } |
| |
| Derived& operator++() |
| { |
| iter_adaptor_access::increment(final()); |
| return final(); |
| } |
| |
| Derived& operator--() |
| { |
| iter_adaptor_access::decrement(final()); |
| return final(); |
| } |
| |
| Derived& operator+=(difference_type n) |
| { |
| iter_adaptor_access::advance(final(),n); |
| return final(); |
| } |
| |
| Derived& operator-=(difference_type n) |
| { |
| iter_adaptor_access::advance(final(),-n); |
| return final(); |
| } |
| |
| friend difference_type operator-(const Derived& x,const Derived& y) |
| { |
| return iter_adaptor_access::distance_to(y,x); |
| } |
| |
| private: |
| Derived& final(){return *static_cast<Derived*>(this);} |
| const Derived& final()const{return *static_cast<const Derived*>(this);} |
| }; |
| |
| template<class Derived,class Base> |
| bool operator==( |
| const random_access_iter_adaptor_base<Derived,Base>& x, |
| const random_access_iter_adaptor_base<Derived,Base>& y) |
| { |
| return iter_adaptor_access::equal( |
| static_cast<const Derived&>(x),static_cast<const Derived&>(y)); |
| } |
| |
| template<class Derived,class Base> |
| bool operator<( |
| const random_access_iter_adaptor_base<Derived,Base>& x, |
| const random_access_iter_adaptor_base<Derived,Base>& y) |
| { |
| return iter_adaptor_access::distance_to( |
| static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0; |
| } |
| |
| template<class Derived,class Base> |
| typename random_access_iter_adaptor_base<Derived,Base>::difference_type |
| operator-( |
| const random_access_iter_adaptor_base<Derived,Base>& x, |
| const random_access_iter_adaptor_base<Derived,Base>& y) |
| { |
| return iter_adaptor_access::distance_to( |
| static_cast<const Derived&>(y),static_cast<const Derived&>(x)); |
| } |
| |
| template<> |
| struct iter_adaptor_selector<std::random_access_iterator_tag> |
| { |
| template<class Derived,class Base> |
| struct apply |
| { |
| typedef random_access_iter_adaptor_base<Derived,Base> type; |
| }; |
| }; |
| |
| template<class Derived,class Base> |
| struct iter_adaptor_base |
| { |
| typedef iter_adaptor_selector< |
| typename Base::iterator_category> selector; |
| typedef typename prevent_eti< |
| selector, |
| typename mpl::apply2< |
| selector,Derived,Base>::type |
| >::type type; |
| }; |
| |
| template<class Derived,class Base> |
| class iter_adaptor:public iter_adaptor_base<Derived,Base>::type |
| { |
| protected: |
| iter_adaptor(){} |
| explicit iter_adaptor(const Base& b_):b(b_){} |
| |
| const Base& base_reference()const{return b;} |
| Base& base_reference(){return b;} |
| |
| private: |
| Base b; |
| }; |
| |
| } /* namespace multi_index::detail */ |
| |
| } /* namespace multi_index */ |
| |
| } /* namespace boost */ |
| |
| #endif |