Chris@16: // Boost.Range library Chris@16: // Chris@16: // Copyright Neil Groves 2010. Use, modification and Chris@16: // distribution is subject to the Boost Software License, Version Chris@16: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // For more information, see http://www.boost.org/libs/range/ Chris@16: // Chris@16: #ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED Chris@16: #define BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace range_detail Chris@16: { Chris@16: // metafunction to determine if T is a const reference Chris@16: template Chris@16: struct is_const_reference Chris@16: { Chris@16: typedef typename mpl::and_< Chris@16: typename is_reference::type, Chris@16: typename is_const< Chris@16: typename remove_reference::type Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // metafunction to determine if T is a mutable reference Chris@16: template Chris@16: struct is_mutable_reference Chris@16: { Chris@16: typedef typename mpl::and_< Chris@16: typename is_reference::type, Chris@16: typename mpl::not_< Chris@16: typename is_const< Chris@16: typename remove_reference::type Chris@16: >::type Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: // metafunction to evaluate if a source 'reference' can be Chris@16: // converted to a target 'reference' as a value. Chris@16: // Chris@16: // This is true, when the target reference type is actually Chris@16: // not a reference, and the source reference is convertible Chris@16: // to the target type. Chris@16: template Chris@16: struct is_convertible_to_value_as_reference Chris@16: { Chris@16: typedef typename mpl::and_< Chris@16: typename mpl::not_< Chris@16: typename is_reference::type Chris@16: >::type Chris@16: , typename is_convertible< Chris@16: SourceReference Chris@16: , TargetReference Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template< Chris@16: class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: , class Buffer = any_iterator_default_buffer Chris@16: > Chris@16: class any_iterator; Chris@16: Chris@16: // metafunction to determine if SomeIterator is an Chris@16: // any_iterator. Chris@16: // Chris@16: // This is the general implementation which evaluates to false. Chris@16: template Chris@16: struct is_any_iterator Chris@16: : mpl::bool_ Chris@16: { Chris@16: }; Chris@16: Chris@16: // specialization of is_any_iterator to return true for Chris@16: // any_iterator classes regardless of template parameters. Chris@16: template< Chris@16: class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: , class Buffer Chris@16: > Chris@16: struct is_any_iterator< Chris@16: any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: > Chris@16: : mpl::bool_ Chris@16: { Chris@16: }; Chris@16: } // namespace range_detail Chris@16: Chris@101: namespace iterators Chris@101: { Chris@16: namespace detail Chris@16: { Chris@16: // Rationale: Chris@16: // These are specialized since the iterator_facade versions lack Chris@16: // the requisite typedefs to allow wrapping to determine the types Chris@16: // if a user copy constructs from a postfix increment. Chris@16: Chris@16: template< Chris@16: class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: , class Buffer Chris@16: > Chris@16: class postfix_increment_proxy< Chris@16: range_detail::any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: > Chris@16: { Chris@16: typedef range_detail::any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > any_iterator_type; Chris@16: Chris@16: public: Chris@16: typedef Value value_type; Chris@16: typedef typename std::iterator_traits::iterator_category iterator_category; Chris@16: typedef Difference difference_type; Chris@16: typedef typename iterator_pointer::type pointer; Chris@16: typedef Reference reference; Chris@16: Chris@16: explicit postfix_increment_proxy(any_iterator_type const& x) Chris@16: : stored_value(*x) Chris@16: {} Chris@16: Chris@16: value_type& Chris@16: operator*() const Chris@16: { Chris@16: return this->stored_value; Chris@16: } Chris@16: private: Chris@16: mutable value_type stored_value; Chris@16: }; Chris@16: Chris@16: template< Chris@16: class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: , class Buffer Chris@16: > Chris@16: class writable_postfix_increment_proxy< Chris@16: range_detail::any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: > Chris@16: { Chris@16: typedef range_detail::any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > any_iterator_type; Chris@16: public: Chris@16: typedef Value value_type; Chris@16: typedef typename std::iterator_traits::iterator_category iterator_category; Chris@16: typedef Difference difference_type; Chris@16: typedef typename iterator_pointer::type pointer; Chris@16: typedef Reference reference; Chris@16: Chris@16: explicit writable_postfix_increment_proxy(any_iterator_type const& x) Chris@16: : stored_value(*x) Chris@16: , stored_iterator(x) Chris@16: {} Chris@16: Chris@16: // Dereferencing must return a proxy so that both *r++ = o and Chris@16: // value_type(*r++) can work. In this case, *r is the same as Chris@16: // *r++, and the conversion operator below is used to ensure Chris@16: // readability. Chris@16: writable_postfix_increment_proxy const& Chris@16: operator*() const Chris@16: { Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Provides readability of *r++ Chris@16: operator value_type&() const Chris@16: { Chris@16: return stored_value; Chris@16: } Chris@16: Chris@16: // Provides writability of *r++ Chris@16: template Chris@16: T const& operator=(T const& x) const Chris@16: { Chris@16: *this->stored_iterator = x; Chris@16: return x; Chris@16: } Chris@16: Chris@16: // This overload just in case only non-const objects are writable Chris@16: template Chris@16: T& operator=(T& x) const Chris@16: { Chris@16: *this->stored_iterator = x; Chris@16: return x; Chris@16: } Chris@16: Chris@16: // Provides X(r++) Chris@16: operator any_iterator_type const&() const Chris@16: { Chris@16: return stored_iterator; Chris@16: } Chris@16: Chris@16: private: Chris@16: mutable value_type stored_value; Chris@16: any_iterator_type stored_iterator; Chris@16: }; Chris@16: Chris@101: } //namespace detail Chris@101: } //namespace iterators Chris@16: Chris@16: namespace range_detail Chris@16: { Chris@16: template< Chris@16: class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: , class Buffer Chris@16: > Chris@16: class any_iterator Chris@16: : public iterator_facade< Chris@16: any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: , Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: > Chris@16: { Chris@16: template< Chris@16: class OtherValue Chris@16: , class OtherTraversal Chris@16: , class OtherReference Chris@16: , class OtherDifference Chris@16: , class OtherBuffer Chris@16: > Chris@16: friend class any_iterator; Chris@16: Chris@16: struct enabler {}; Chris@16: struct disabler {}; Chris@16: Chris@16: typedef typename any_iterator_interface_type_generator< Chris@16: Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: >::type abstract_base_type; Chris@16: Chris@16: typedef iterator_facade< Chris@16: any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: , Value Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: > base_type; Chris@16: Chris@16: typedef Buffer buffer_type; Chris@16: Chris@16: public: Chris@16: typedef typename base_type::value_type value_type; Chris@16: typedef typename base_type::reference reference; Chris@16: typedef typename base_type::difference_type difference_type; Chris@16: Chris@16: // Default constructor Chris@16: any_iterator() Chris@16: : m_impl(0) {} Chris@16: Chris@16: // Simple copy construction without conversion Chris@16: any_iterator(const any_iterator& other) Chris@16: : base_type(other) Chris@16: , m_impl(other.m_impl Chris@16: ? other.m_impl->clone(m_buffer) Chris@16: : 0) Chris@16: { Chris@16: } Chris@16: Chris@16: // Simple assignment operator without conversion Chris@16: any_iterator& operator=(const any_iterator& other) Chris@16: { Chris@16: if (this != &other) Chris@16: { Chris@16: if (m_impl) Chris@16: m_impl->~abstract_base_type(); Chris@16: m_buffer.deallocate(); Chris@16: m_impl = 0; Chris@16: if (other.m_impl) Chris@16: m_impl = other.m_impl->clone(m_buffer); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Implicit conversion from another any_iterator where the Chris@16: // conversion is from a non-const reference to a const reference Chris@16: template< Chris@16: class OtherValue Chris@16: , class OtherTraversal Chris@16: , class OtherReference Chris@16: , class OtherDifference Chris@16: > Chris@16: any_iterator(const any_iterator< Chris@16: OtherValue, Chris@16: OtherTraversal, Chris@16: OtherReference, Chris@16: OtherDifference, Chris@16: Buffer Chris@16: >& other, Chris@101: typename ::boost::enable_if< Chris@16: typename mpl::and_< Chris@16: typename is_mutable_reference::type, Chris@16: typename is_const_reference::type Chris@16: >::type, Chris@16: enabler Chris@16: >::type* = 0 Chris@16: ) Chris@16: : m_impl(other.m_impl Chris@16: ? other.m_impl->clone_const_ref(m_buffer) Chris@16: : 0 Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: // Implicit conversion from another any_iterator where the Chris@16: // reference types of the source and the target are references Chris@16: // that are either both const, or both non-const. Chris@16: template< Chris@16: class OtherValue Chris@16: , class OtherTraversal Chris@16: , class OtherReference Chris@16: , class OtherDifference Chris@16: > Chris@16: any_iterator(const any_iterator< Chris@16: OtherValue Chris@16: , OtherTraversal Chris@16: , OtherReference Chris@16: , OtherDifference Chris@16: , Buffer Chris@16: >& other, Chris@101: typename ::boost::enable_if< Chris@16: typename mpl::or_< Chris@16: typename mpl::and_< Chris@16: typename is_mutable_reference::type, Chris@16: typename is_mutable_reference::type Chris@16: >::type, Chris@16: typename mpl::and_< Chris@16: typename is_const_reference::type, Chris@16: typename is_const_reference::type Chris@16: >::type Chris@16: >::type, Chris@16: enabler Chris@16: >::type* = 0 Chris@16: ) Chris@16: : m_impl(other.m_impl Chris@16: ? other.m_impl->clone(m_buffer) Chris@16: : 0 Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: // Implicit conversion to an any_iterator that uses a value for Chris@16: // the reference type. Chris@16: template< Chris@16: class OtherValue Chris@16: , class OtherTraversal Chris@16: , class OtherReference Chris@16: , class OtherDifference Chris@16: > Chris@16: any_iterator(const any_iterator< Chris@16: OtherValue Chris@16: , OtherTraversal Chris@16: , OtherReference Chris@16: , OtherDifference Chris@16: , Buffer Chris@16: >& other, Chris@101: typename ::boost::enable_if< Chris@16: typename is_convertible_to_value_as_reference< Chris@16: OtherReference Chris@16: , Reference Chris@16: >::type, Chris@16: enabler Chris@16: >::type* = 0 Chris@16: ) Chris@16: : m_impl(other.m_impl Chris@16: ? other.m_impl->clone_reference_as_value(m_buffer) Chris@16: : 0 Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: any_iterator clone() const Chris@16: { Chris@16: any_iterator result; Chris@16: if (m_impl) Chris@16: result.m_impl = m_impl->clone(result.m_buffer); Chris@16: return result; Chris@16: } Chris@16: Chris@16: any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , typename abstract_base_type::const_reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > Chris@16: clone_const_ref() const Chris@16: { Chris@16: typedef any_iterator< Chris@16: Value Chris@16: , Traversal Chris@16: , typename abstract_base_type::const_reference Chris@16: , Difference Chris@16: , Buffer Chris@16: > result_type; Chris@16: Chris@16: result_type result; Chris@16: Chris@16: if (m_impl) Chris@16: result.m_impl = m_impl->clone_const_ref(result.m_buffer); Chris@16: Chris@16: return result; Chris@16: } Chris@16: Chris@16: // implicit conversion and construction from type-erasure-compatible Chris@16: // iterators Chris@16: template Chris@16: explicit any_iterator( Chris@16: const WrappedIterator& wrapped_iterator, Chris@16: typename disable_if< Chris@16: typename is_any_iterator::type Chris@16: , disabler Chris@16: >::type* = 0 Chris@16: ) Chris@16: { Chris@16: typedef typename any_iterator_wrapper_type_generator< Chris@16: WrappedIterator Chris@16: , Traversal Chris@16: , Reference Chris@16: , Difference Chris@16: , Buffer Chris@16: >::type wrapper_type; Chris@16: Chris@16: void* ptr = m_buffer.allocate(sizeof(wrapper_type)); Chris@16: m_impl = new(ptr) wrapper_type(wrapped_iterator); Chris@16: } Chris@16: Chris@16: ~any_iterator() Chris@16: { Chris@16: // manually run the destructor, the deallocation is automatically Chris@16: // handled by the any_iterator_small_buffer base class. Chris@16: if (m_impl) Chris@16: m_impl->~abstract_base_type(); Chris@16: } Chris@16: Chris@16: private: Chris@16: friend class ::boost::iterator_core_access; Chris@16: Chris@16: Reference dereference() const Chris@16: { Chris@16: BOOST_ASSERT( m_impl ); Chris@16: return m_impl->dereference(); Chris@16: } Chris@16: Chris@16: bool equal(const any_iterator& other) const Chris@16: { Chris@16: return (m_impl == other.m_impl) Chris@16: || (m_impl && other.m_impl && m_impl->equal(*other.m_impl)); Chris@16: } Chris@16: Chris@16: void increment() Chris@16: { Chris@16: BOOST_ASSERT( m_impl ); Chris@16: m_impl->increment(); Chris@16: } Chris@16: Chris@16: void decrement() Chris@16: { Chris@16: BOOST_ASSERT( m_impl ); Chris@16: m_impl->decrement(); Chris@16: } Chris@16: Chris@16: Difference distance_to(const any_iterator& other) const Chris@16: { Chris@16: return m_impl && other.m_impl Chris@16: ? m_impl->distance_to(*other.m_impl) Chris@16: : 0; Chris@16: } Chris@16: Chris@16: void advance(Difference offset) Chris@16: { Chris@16: BOOST_ASSERT( m_impl ); Chris@16: m_impl->advance(offset); Chris@16: } Chris@16: Chris@16: any_iterator& swap(any_iterator& other) Chris@16: { Chris@16: BOOST_ASSERT( this != &other ); Chris@16: // grab a temporary copy of the other iterator Chris@16: any_iterator tmp(other); Chris@16: Chris@16: // deallocate the other iterator, taking care to obey the Chris@16: // class-invariants in-case of exceptions later Chris@16: if (other.m_impl) Chris@16: { Chris@16: other.m_impl->~abstract_base_type(); Chris@16: other.m_buffer.deallocate(); Chris@16: other.m_impl = 0; Chris@16: } Chris@16: Chris@16: // If this is a non-null iterator then we need to put Chris@16: // a clone of this iterators implementation into the other Chris@16: // iterator. Chris@16: // We can't just swap because of the small buffer optimization. Chris@16: if (m_impl) Chris@16: { Chris@16: other.m_impl = m_impl->clone(other.m_buffer); Chris@16: m_impl->~abstract_base_type(); Chris@16: m_buffer.deallocate(); Chris@16: m_impl = 0; Chris@16: } Chris@16: Chris@16: // assign to this instance a clone of the temporarily held Chris@16: // tmp which represents the input other parameter at the Chris@16: // start of execution of this function. Chris@16: if (tmp.m_impl) Chris@16: m_impl = tmp.m_impl->clone(m_buffer); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: buffer_type m_buffer; Chris@16: abstract_base_type* m_impl; Chris@16: }; Chris@16: Chris@16: } // namespace range_detail Chris@16: } // namespace boost Chris@16: Chris@16: #endif // include guard