From 43c117e4002863f56c53622ea3e8d5d4f81eac2a Mon Sep 17 00:00:00 2001 From: Madzik Date: Fri, 26 Jan 2018 19:22:40 +0100 Subject: [PATCH] add any_terator --- share/any_iterator/any_iterator.hpp | 422 +++++++++++++++++ .../detail/any_iterator_abstract_base.hpp | 255 ++++++++++ .../detail/any_iterator_metafunctions.hpp | 363 ++++++++++++++ .../detail/any_iterator_wrapper.hpp | 443 ++++++++++++++++++ 4 files changed, 1483 insertions(+) create mode 100644 share/any_iterator/any_iterator.hpp create mode 100644 share/any_iterator/detail/any_iterator_abstract_base.hpp create mode 100644 share/any_iterator/detail/any_iterator_metafunctions.hpp create mode 100644 share/any_iterator/detail/any_iterator_wrapper.hpp diff --git a/share/any_iterator/any_iterator.hpp b/share/any_iterator/any_iterator.hpp new file mode 100644 index 0000000..0d6fdb9 --- /dev/null +++ b/share/any_iterator/any_iterator.hpp @@ -0,0 +1,422 @@ +// (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// ================ +// +// 27 Dec 2006 (Thomas Becker) Created + +#ifndef ANY_ITERATOR_01102007TMB_HPP +#define ANY_ITERATOR_01102007TMB_HPP + +// Includes +// ======== + +#include "detail/any_iterator_abstract_base.hpp" +#include "detail/any_iterator_wrapper.hpp" +#include "detail/any_iterator_metafunctions.hpp" +#include +#include +#include +#include +#include +#include + +namespace IteratorTypeErasure +{ + + /////////////////////////////////////////////////////////////////////// + // + // The any_iterator is modeled after the "type erasure pattern" as set + // forth in boost::any. The class names correspond as follows: + // + // boost::any ==> any_iterator + // boost::any::placeholder ==> any_iterator_abstract_base + // boost::any::holder ==> any_iterator_wrapper + // + template< + class Value, + class CategoryOrTraversal, + class Reference = Value&, + class Difference = std::ptrdiff_t + > + class any_iterator : + public boost::iterator_facade< + any_iterator< + Value, + CategoryOrTraversal, + Reference, + Difference + >, + Value, + CategoryOrTraversal, + Reference, + Difference + > + { + + // We make every other any_iterator our friend. This is needed only for + // the conversion from non-const to const, but there should be no harm + // in being overly friendly here. + template< + class OtherValue, + class OtherCategoryOrTraversal, + class OtherReference, + class OtherDifference + > + friend class any_iterator; + + public: + typedef typename boost::iterator_category_to_traversal::type Traversal; + + private: + + struct enabler{}; // a private type avoids misuse + struct disabler{}; // a private type avoids misuse + + // The type-erasing abstract base class, that is, the type that the + // impl-pointer points to. + typedef + detail::any_iterator_abstract_base< + Value, + Traversal, + Reference, + Difference + > abstract_base_type; + + typedef + boost::iterator_facade< + any_iterator< + Value, + CategoryOrTraversal, + Reference, + Difference + >, + Value, + CategoryOrTraversal, + Reference, + Difference + > super_type; + + // The two types that this any_iterator type recognizes as const versions of + // itself. + typedef any_iterator< + typename boost::add_const::type, + CategoryOrTraversal, + typename detail::make_iterator_reference_const::type, + Difference + > const_type_with_const_value_type; + // + typedef any_iterator< + typename boost::remove_const::type, + CategoryOrTraversal, + typename detail::make_iterator_reference_const::type, + Difference + > const_type_with_non_const_value_type; + + public: + + any_iterator() : m_pointer_to_impl(NULL) + {} + + any_iterator(any_iterator const & rhs) : super_type(rhs) + { + if( rhs.m_pointer_to_impl ) + { + m_pointer_to_impl = rhs.m_pointer_to_impl->clone(); + } + else + { + m_pointer_to_impl = NULL; + } + } + + any_iterator& operator=(any_iterator const & rhs) + { + if(this != &rhs) + { + any_iterator tmp(rhs); + swap(tmp); + } + + return *this; + } + + // Constructor from wrapped iterator. The static assert defines the + // granularity of the type erasure. + // + // NOTE 1: If you want to make the constructor non-explicit, then you + // really must replace the static assert with an enable_if, or else + // metafunctions such as is_convertible will say the wrong thing. + // However, if you use enable_if here, you'll descend into the ugly + // mess described in the last section of my article at + // http://www.artima.com/cppsource/type_erasure.html. + // + // NOTE 2: If you remove the restriction that the wrapped iterator + // cannot be an any_iterator, you must ensure that the conversions from + // non-const to const any_iterators still work correctly. If you don't + // do anything, you will end up with wrapping instead of conversion. + // + template + explicit any_iterator( + WrappedIterator const & wrapped_iterator, + typename boost::disable_if< + detail::is_any_iterator, + disabler + >::type = disabler() + ) + { + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If this static assert fires, you are trying to construct the any_iterator + // from a concrete iterator that is not suitable for the type erasure that + // the any_iterator provides. + // + BOOST_STATIC_ASSERT((detail::is_iterator_type_erasure_compatible::type::value)); + + typedef + detail::any_iterator_wrapper< + WrappedIterator, + Value, + Traversal, + Reference, + Difference + > wrapper_type; + + m_pointer_to_impl = wrapper_type::create(wrapped_iterator); + } + + // Assignment from wrapped iterator. The enable_if condition defines + // the granularity of the type erasure. + // + // NOTE: If you remove the restriction that the wrapped iterator + // cannot be an any_iterator, you must ensure that the conversions from + // non-const to const any_iterators still work correctly. If you don't + // do anything, you will end up with wrapping instead of conversion. + template + typename boost::enable_if< + boost::mpl::and_< + detail::is_iterator_type_erasure_compatible, + boost::mpl::not_ > + >, + any_iterator + >::type & + operator=(WrappedIterator const & wrapped_iterator) + { + any_iterator tmp(wrapped_iterator); + swap(tmp); + return *this; + } + + // Conversion from non-const to const any_iterator. There are two versions. + // This first one applies if the target has const value type. + operator const_type_with_const_value_type () const + { + const_type_with_const_value_type conversion_result; + if( m_pointer_to_impl ) + { + conversion_result.m_pointer_to_impl = m_pointer_to_impl->make_const_clone_with_const_value_type(); + } + return conversion_result; + } + + // Conversion from non-const to const any_iterator. There are two versions. + // This second one applies if the target has non-const value type. + operator const_type_with_non_const_value_type () const + { + const_type_with_non_const_value_type conversion_result; + if( m_pointer_to_impl ) + { + conversion_result.m_pointer_to_impl = m_pointer_to_impl->make_const_clone_with_non_const_value_type(); + } + return conversion_result; + } + + // Conversion to weaker traversal type + template + operator any_iterator< + Value, + TargetTraversal, + Reference, + Difference + > + () const + { + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If this static assert fires, you are trying to convert between two + // any_iterator types that are not suitable for conversion. + // + BOOST_STATIC_ASSERT(( + boost::is_base_of< + typename boost::iterator_category_to_traversal::type, + typename boost::iterator_category_to_traversal::type + >::type::value + )); + + any_iterator< + Value, + TargetTraversal, + Reference, + Difference + > conversion_result; + + if( m_pointer_to_impl ) + { + typename boost::iterator_category_to_traversal::type* funcSelector = NULL; + conversion_result.m_pointer_to_impl = make_traversal_converted_version(funcSelector); + } + return conversion_result; + } + + ~any_iterator() + { + delete m_pointer_to_impl; + } + + private: + + friend class boost::iterator_core_access; + + Reference dereference() const + { + return m_pointer_to_impl->dereference(); + } + + bool equal(any_iterator const & rhs) const + { + if( m_pointer_to_impl == rhs.m_pointer_to_impl ) + { + return true; + } + + if( m_pointer_to_impl == NULL || rhs.m_pointer_to_impl == NULL ) + { + return false; + } + + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If the next line does not compile, you are trying to compare + // two iterators for equality whose categories do not allow that + // comparison. + return m_pointer_to_impl->equal(*(rhs.m_pointer_to_impl)); + } + + void increment() + { + m_pointer_to_impl->increment(); + } + + void decrement() + { + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If the next line does not compile, you are trying to decrement + // an iterator whose category does not allow decrementing. + return m_pointer_to_impl->decrement(); + } + + void advance(Difference n) + { + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If the next line does not compile, you are trying to use an + // operation that is defined only for random access iterators + // on an iterator that is not random access. + m_pointer_to_impl->advance(n); + } + + Difference distance_to(any_iterator const & other) const + { + ////////////////////////////////////////////////////////////////// + // + // *** Message to Client *** + // + // If the next line does not compile, you are trying to use an + // operation that is defined only for random access iterators + // on an iterator that is not random access. + return m_pointer_to_impl->distance_to(*(other.m_pointer_to_impl)); + } + + any_iterator& swap(any_iterator& other) + { + // NOTE: iterator_facade doesn't have a swap method, so no call + // to base class here. + std::swap(m_pointer_to_impl, other.m_pointer_to_impl); + return *this; + } + + detail::any_iterator_abstract_base< + Value, + boost::incrementable_traversal_tag, + Reference, + Difference + >* make_traversal_converted_version(boost::incrementable_traversal_tag* funcSelector) const + { + return m_pointer_to_impl->make_incrementable_version(); + } + + detail::any_iterator_abstract_base< + Value, + boost::single_pass_traversal_tag, + Reference, + Difference + >* make_traversal_converted_version(boost::single_pass_traversal_tag* funcSelector) const + { + return m_pointer_to_impl->make_single_pass_version(); + } + + detail::any_iterator_abstract_base< + Value, + boost::forward_traversal_tag, + Reference, + Difference + >* make_traversal_converted_version(boost::forward_traversal_tag* funcSelector) const + { + return m_pointer_to_impl->make_forward_version(); + } + + detail::any_iterator_abstract_base< + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference + >* make_traversal_converted_version(boost::bidirectional_traversal_tag* funcSelector) const + { + return m_pointer_to_impl->make_bidirectional_version(); + } + + abstract_base_type* m_pointer_to_impl; + + }; + + // Metafunction that takes an iterator and returns an any_iterator with the same + // traits. + template + struct make_any_iterator_type + { + typedef + any_iterator< + typename boost::iterator_value::type, + typename boost::iterator_category::type, + typename boost::iterator_reference::type, + typename boost::iterator_difference::type + > type; + }; + +} // end namespace IteratorTypeErasure + +#endif // ANY_ITERATOR_01102007TMB_HPP diff --git a/share/any_iterator/detail/any_iterator_abstract_base.hpp b/share/any_iterator/detail/any_iterator_abstract_base.hpp new file mode 100644 index 0000000..ed388c7 --- /dev/null +++ b/share/any_iterator/detail/any_iterator_abstract_base.hpp @@ -0,0 +1,255 @@ +// (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// ================ +// +// 27 Dec 2006 (Thomas Becker) Created + +#ifndef ANY_ITERATOR_ABSTRACT_BASE_01102007TMB_HPP +#define ANY_ITERATOR_ABSTRACT_BASE_01102007TMB_HPP + +// Includes +// ======== + +#include "any_iterator_metafunctions.hpp" +#include +#include +#include + +namespace IteratorTypeErasure +{ + + namespace detail + { + + /////////////////////////////////////////////////////////////////////// + // + // The partial specializations of any_iterator_abstract_base (which is + // the equivalent of boost::any::placeholder) mirror the hierarchy of + // boost's iterator traversal tags. + // + // The first four template arguments are as in boost::iterator_facade. + // The last template argument is the traversal tag of the most + // derived class of the current instantiation of the hierarchy. This + // is a slight variant of the CRTP where the derived class passes + // itself as a template argument to the base class(es). Here, it seemed + // more convenient to pass up just the traversal tag of the most + // derived class. + // + template< + class Value, + class Traversal, + class Reference, + class Difference, + class UsedAsBaseForTraversal = Traversal + > + class any_iterator_abstract_base; + + /////////////////////////////////////////////////////////////////////// + // + template< + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_abstract_base< + Value, + boost::incrementable_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + protected: + typedef any_iterator_abstract_base< + Value, + UsedAsBaseForTraversal, + Reference, + Difference + > most_derived_type; + + typedef most_derived_type clone_result_type; + + typedef any_iterator_abstract_base< + typename boost::add_const::type, + UsedAsBaseForTraversal, + typename make_iterator_reference_const::type, + Difference + > const_clone_with_const_value_type_result_type; + + typedef any_iterator_abstract_base< + typename boost::remove_const::type, + UsedAsBaseForTraversal, + typename make_iterator_reference_const::type, + Difference + > const_clone_with_non_const_value_type_result_type; + + public: + + // Plain clone function for copy construction and assignment. + virtual clone_result_type * clone() const=0; + + // Clone functions for conversion to a const iterator + virtual const_clone_with_const_value_type_result_type * make_const_clone_with_const_value_type() const=0; + virtual const_clone_with_non_const_value_type_result_type * make_const_clone_with_non_const_value_type() const=0; + + // gcc 3.4.2 does not like pure virtual declaration with inline definition, + // so I make the destructor non-pure just to spite them. + virtual ~any_iterator_abstract_base() + {} + + virtual Reference dereference() const=0; + virtual void increment() = 0; + + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_abstract_base< + Value, + boost::single_pass_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_abstract_base< + Value, + boost::incrementable_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + // gcc 3.4.2 insists on qualification of most_derived_type. + virtual bool equal(typename any_iterator_abstract_base::most_derived_type const &) const = 0; + + virtual any_iterator_abstract_base< + Value, + boost::incrementable_traversal_tag, + Reference, + Difference + >* make_incrementable_version() const=0; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_abstract_base< + Value, + boost::forward_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_abstract_base< + Value, + boost::single_pass_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + public: + virtual any_iterator_abstract_base< + Value, + boost::single_pass_traversal_tag, + Reference, + Difference + >* make_single_pass_version() const=0; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_abstract_base< + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_abstract_base< + Value, + boost::forward_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + virtual void decrement() = 0; + + virtual any_iterator_abstract_base< + Value, + boost::forward_traversal_tag, + Reference, + Difference + >* make_forward_version() const=0; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_abstract_base< + Value, + boost::random_access_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_abstract_base< + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + virtual void advance(Difference) = 0; + + // gcc 3.4.2 insists on qualification of most_derived_type. + virtual Difference distance_to(typename any_iterator_abstract_base::most_derived_type const &) const= 0; + + virtual any_iterator_abstract_base< + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference + >* make_bidirectional_version() const=0; + }; + + } // end namespace detail + +} // end namespace IteratorTypeErasure + +#endif // ANY_ITERATOR_ABSTRACT_BASE_01102007TMB_HPP diff --git a/share/any_iterator/detail/any_iterator_metafunctions.hpp b/share/any_iterator/detail/any_iterator_metafunctions.hpp new file mode 100644 index 0000000..9a928bc --- /dev/null +++ b/share/any_iterator/detail/any_iterator_metafunctions.hpp @@ -0,0 +1,363 @@ +// (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// File Name +// ========= +// +// metafunctions.h + +// Description +// =========== +// +// Metafunctions for any_iterator + +#ifndef ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP +#define ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP + +// Revision History +// ================ +// +// 27 Dec 2006 (Thomas Becker) Created + +// Includes +// ======== +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace IteratorTypeErasure +{ + + template< + class Value, + class Traversal, + class Reference, + class Difference + > + class any_iterator; + + namespace detail + { + + /////////////////////////////////////////////////////////////////////// + // + template + struct remove_reference_and_const + { + typedef typename boost::remove_const< + typename boost::remove_reference< + typename boost::remove_const< + T + >::type + >::type + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template + struct make_iterator_reference_const + { + typedef typename boost::mpl::if_< + typename boost::is_reference::type, + typename boost::remove_const< + typename boost::remove_reference< + typename boost::remove_const< + IteratorReference + >::type + >::type + >::type const &, + typename boost::remove_const< + typename boost::remove_reference< + typename boost::remove_const< + IteratorReference + >::type + >::type + >::type const + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct value_types_erasure_compatible + { + // Really, we just want WrappedIterator's value_type to convert to + // AnyIterator's value_type. But many real world output iterators + // define their value_type as void. Therefore, we simply ignore + // the value type for output iterators. That's fine because for + // output iterators, the relevant type erasure information is all + // in the reference type. + + typedef typename boost::mpl::or_< + boost::is_same< + typename boost::iterator_category::type, + std::output_iterator_tag + >, + + // Really, we just want WrappedIterator's value_type to convert to + // AnyIterator's value_type. But we need to work around a flaw in + // boost::is_convertible. boost::is_convertible::value is + // false whenever X and Y are abstract base classes (even when X + // and Y are the same). This will be fixed in C++ concepts. + boost::mpl::or_< + boost::is_same< + typename boost::iterator_value::type, + typename boost::iterator_value::type + >, + boost::is_base_of< + typename boost::iterator_value::type, + typename boost::iterator_value::type + >, + boost::is_convertible< + typename boost::iterator_value::type, + typename boost::iterator_value::type + > + > + > type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct reference_types_erasure_compatible_1 + { + typedef typename boost::is_convertible< + typename boost::iterator_reference::type, + typename boost::iterator_reference::type + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct reference_types_erasure_compatible_2 + { + typedef typename boost::mpl::if_< + boost::is_reference< + typename boost::iterator_reference::type + >, + boost::is_reference< + typename boost::iterator_reference::type + >, + boost::mpl::bool_ + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct reference_types_erasure_compatible_3 + { + + typedef typename boost::mpl::if_< + boost::mpl::and_< + boost::is_reference< + typename boost::iterator_reference::type + >, + boost::is_reference< + typename boost::iterator_reference::type + > + >, + boost::mpl::or_< + boost::is_same< + typename remove_reference_and_const< + typename boost::iterator_reference::type + >::type, + typename remove_reference_and_const< + typename boost::iterator_reference::type + >::type + >, + boost::is_base_of< + typename remove_reference_and_const< + typename boost::iterator_reference::type + >::type, + typename remove_reference_and_const< + typename boost::iterator_reference::type + >::type + > + >, + boost::mpl::bool_ + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct reference_types_erasure_compatible + { + // Output iterators are weird. Many real world output iterators + // define their reference type as void. In the world of boost + // iterators, that's terribly wrong, because in that world, an + // iterator's reference type is always the result type of + // operator* (and that makes very good sense, too). Therefore, + // when WrappedIterator is an output iterator, we use + // WrappedIterator& for WrappedIterator's reference type, + // because that's the real, true reference type. Moreover, + // we just require that WrappedIterator& convert to AnyIterator's + // reference type. The other subtleties are not relevant. + + typedef typename boost::mpl::if_< + boost::is_same< + typename boost::iterator_category::type, + std::output_iterator_tag + >, + boost::is_convertible< + WrappedIterator&, + typename boost::iterator_reference::type + >, + boost::mpl::and_< + + // WrappedIterator's reference type must convert to AnyIterator's reference type. + typename reference_types_erasure_compatible_1::type, + + // If AnyIterator's reference type is a reference, then the + // same must be true for WrappedIterator's reference type. + typename reference_types_erasure_compatible_2::type, + + // If AnyIterator's reference type and WrappedIterator's + // reference type are both references, then one of the + // following must hold: + // + // 1) AnyIterator's reference type and WrappedIterator's + // reference type are the same. + // + // 2) AnyIterator's reference type is a base class of WrappedIterator's + // reference type. + // + typename reference_types_erasure_compatible_3::type + > + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct difference_types_erasure_compatible + { + + // Difference type matters only for random access iterators. + + typedef typename boost::mpl::or_< + boost::mpl::not_< + boost::is_same< + // Do not use boost::iterator_traversal::type here, + // as it does not equal the traversal tag. + typename AnyIterator::Traversal, + boost::random_access_traversal_tag + > + >, + boost::mpl::and_< + boost::is_convertible< + typename boost::iterator_difference::type, + typename boost::iterator_difference::type + >, + boost::is_convertible< + typename boost::iterator_difference::type, + typename boost::iterator_difference::type + > + > + > type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct traversal_types_erasure_compatible + { + typedef typename boost::mpl::or_< + boost::is_same< + // Do not use boost::iterator_traversal::type here, + // as it does not equal the traversal tag. + typename AnyIterator::Traversal, + typename boost::iterator_traversal::type + >, + boost::is_base_of< + // Do not use boost::iterator_traversal::type here, + // as it does not equal the traversal tag. + typename AnyIterator::Traversal, + typename boost::iterator_traversal::type + > + > type; + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class AnyIterator + > + struct is_iterator_type_erasure_compatible : + public boost::mpl::bool_< + boost::mpl::and_< + value_types_erasure_compatible, + reference_types_erasure_compatible, + difference_types_erasure_compatible, + traversal_types_erasure_compatible + >::value + > + { + }; + + /////////////////////////////////////////////////////////////////////// + // + template + struct is_any_iterator : public boost::mpl::bool_ + { + }; + // + template< + class Value, + class Traversal, + class Reference, + class Difference + > + struct is_any_iterator< + any_iterator< + Value, + Traversal, + Reference, + Difference + > + > : public boost::mpl::bool_ + { + }; + + } // end namespace detail + +} // end namespace IteratorTypeErasure + +#endif // ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP diff --git a/share/any_iterator/detail/any_iterator_wrapper.hpp b/share/any_iterator/detail/any_iterator_wrapper.hpp new file mode 100644 index 0000000..1770fd2 --- /dev/null +++ b/share/any_iterator/detail/any_iterator_wrapper.hpp @@ -0,0 +1,443 @@ +// (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// ================ +// +// 27 Dec 2006 (Thomas Becker) Created +// 12 Jul 2010 (Thomas Becker acting on bug report by Edgar Binder) +// Bug fix: Constructors and create function of any_iterator_wrapper +// from wrapped iterator must take their argument by const reference (performance!). + +#ifndef ANY_ITERATOR_WRAPPER_01102007TMB_HPP +#define ANY_ITERATOR_WRAPPER_01102007TMB_HPP + +// Includes +// ======== + +#include "any_iterator_abstract_base.hpp" +#include "any_iterator_metafunctions.hpp" +#include +#include +#include + +namespace IteratorTypeErasure +{ + + namespace detail + { + + /////////////////////////////////////////////////////////////////////// + // + // The partial specializations of any_iterator_wrapper (which is the + // the equivalent of boost::any::holder) mirror the hierarchy of + // boost's iterator traversal tags. + // + // The first four template arguments are as in boost::iterator_facade. + // The last template argument is the traversal tag of the most + // derived class of the current instantiation of the hierarchy. This + // is a slight variant of the CRTP where the derived class passes + // itself as a template argument to the base class(es). Here, it seemed + // more convenient to pass up just the traversal tag of the most + // derived class. + // + template< + class WrappedIterator, + class Value, + class Traversal, + class Reference, + class Difference, + class UsedAsBaseForTraversal = Traversal + > + class any_iterator_wrapper; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_wrapper< + WrappedIterator, + Value, + boost::incrementable_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_abstract_base< + Value, + UsedAsBaseForTraversal, + Reference, + Difference + > + { + + protected: + typedef any_iterator_abstract_base abstract_base_type; + + private: + typedef typename abstract_base_type::clone_result_type clone_result_type; + typedef typename abstract_base_type::const_clone_with_const_value_type_result_type const_clone_with_const_value_type_result_type; + typedef typename abstract_base_type::const_clone_with_non_const_value_type_result_type const_clone_with_non_const_value_type_result_type; + + typedef any_iterator_wrapper< + WrappedIterator, + Value, + UsedAsBaseForTraversal, + Reference, + Difference + > clone_type; + + typedef any_iterator_wrapper< + WrappedIterator, + typename boost::add_const::type, + UsedAsBaseForTraversal, + typename make_iterator_reference_const::type, + Difference + > const_clone_type_with_const_value_type; + + typedef any_iterator_wrapper< + WrappedIterator, + typename boost::remove_const::type, + UsedAsBaseForTraversal, + typename make_iterator_reference_const::type, + Difference + > const_clone_type_with_non_const_value_type; + + public: + + any_iterator_wrapper() + {} + + any_iterator_wrapper(WrappedIterator const& wrapped_iterator) : + m_wrapped_iterator(wrapped_iterator) + {} + + static abstract_base_type* create(WrappedIterator const& wrapped_iterator) + { + return new clone_type(wrapped_iterator); + } + + // Plain clone function for copy construction and assignment. + virtual clone_result_type * clone() const + { + return new clone_type(m_wrapped_iterator); + } + + // Clone functions for conversion to a const iterator + virtual const_clone_with_const_value_type_result_type* make_const_clone_with_const_value_type() const + { + return new const_clone_type_with_const_value_type(m_wrapped_iterator); + } + // + virtual const_clone_with_non_const_value_type_result_type* make_const_clone_with_non_const_value_type() const + { + return new const_clone_type_with_non_const_value_type(m_wrapped_iterator); + } + + virtual Reference dereference() const + { + // This const cast is needed for output iterators. Is this perhaps an oversight + // in iterator_facade? + return *const_cast(this)->m_wrapped_iterator; + } + + virtual void increment() + { + ++m_wrapped_iterator; + } + + protected: + + WrappedIterator& get_wrapped_iterator() + { + return m_wrapped_iterator; + } + + WrappedIterator const & get_wrapped_iterator() const + { + return m_wrapped_iterator; + } + + private: + + WrappedIterator m_wrapped_iterator; + + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_wrapper< + WrappedIterator, + Value, + boost::single_pass_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_wrapper< + WrappedIterator, + Value, + boost::incrementable_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + typedef + any_iterator_wrapper< + WrappedIterator, + Value, + boost::incrementable_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > super_type; + + any_iterator_wrapper() + {} + + any_iterator_wrapper(WrappedIterator const& wrapped_iterator) : super_type(wrapped_iterator) + {} + + // gcc 3.4.2 insists on qualification of abstract_base_type. + virtual bool equal(typename any_iterator_wrapper::abstract_base_type const & rhs) const + { + return this->get_wrapped_iterator() == boost::polymorphic_downcast(&rhs)->get_wrapped_iterator(); + } + + any_iterator_abstract_base< + Value, + boost::incrementable_traversal_tag, + Reference, + Difference + >* make_incrementable_version() const + { + return new any_iterator_wrapper< + WrappedIterator, + Value, + boost::incrementable_traversal_tag, + Reference, + Difference + >(this->get_wrapped_iterator()); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_wrapper< + WrappedIterator, + Value, + boost::forward_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_wrapper< + WrappedIterator, + Value, + boost::single_pass_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + typedef + any_iterator_wrapper< + WrappedIterator, + Value, + boost::single_pass_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > super_type; + + any_iterator_wrapper() + {} + + any_iterator_wrapper(WrappedIterator const& wrapped_iterator) : super_type(wrapped_iterator) + {} + + any_iterator_abstract_base< + Value, + boost::single_pass_traversal_tag, + Reference, + Difference + >* make_single_pass_version() const + { + return new any_iterator_wrapper< + WrappedIterator, + Value, + boost::single_pass_traversal_tag, + Reference, + Difference + >(this->get_wrapped_iterator()); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_wrapper< + WrappedIterator, + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_wrapper< + WrappedIterator, + Value, + boost::forward_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + typedef + any_iterator_wrapper< + WrappedIterator, + Value, + boost::forward_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > super_type; + + any_iterator_wrapper() + {} + + any_iterator_wrapper(WrappedIterator const& wrapped_iterator) : super_type(wrapped_iterator) + {} + + virtual void decrement() + { + --(this->get_wrapped_iterator()); + } + + any_iterator_abstract_base< + Value, + boost::forward_traversal_tag, + Reference, + Difference + >* make_forward_version() const + { + return new any_iterator_wrapper< + WrappedIterator, + Value, + boost::forward_traversal_tag, + Reference, + Difference + >(this->get_wrapped_iterator()); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + template< + class WrappedIterator, + class Value, + class Reference, + class Difference, + class UsedAsBaseForTraversal + > + class any_iterator_wrapper< + WrappedIterator, + Value, + boost::random_access_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > : public any_iterator_wrapper< + WrappedIterator, + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > + { + + public: + + typedef + any_iterator_wrapper< + WrappedIterator, + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference, + UsedAsBaseForTraversal + > super_type; + + any_iterator_wrapper() + {} + + any_iterator_wrapper(WrappedIterator const& wrapped_iterator) : super_type(wrapped_iterator) + {} + + virtual void advance(Difference n) + { + this->get_wrapped_iterator() += n; + } + + // gcc 3.4.2 insists on qualification of abstract_base_type. + virtual Difference distance_to(typename any_iterator_wrapper::abstract_base_type const & other) const + { + return boost::polymorphic_downcast(&other)->get_wrapped_iterator() - this->get_wrapped_iterator(); + } + + any_iterator_abstract_base< + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference + >* make_bidirectional_version() const + { + return new any_iterator_wrapper< + WrappedIterator, + Value, + boost::bidirectional_traversal_tag, + Reference, + Difference + >(this->get_wrapped_iterator()); + } + }; + + } // end namespace detail + +} // end namespace IteratorTypeErasure + +#endif // ANY_ITERATOR_WRAPPER_01102007TMB_HPP