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