123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- // 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 <boost/mpl/and.hpp>
- #include <boost/mpl/or.hpp>
- #include <boost/mpl/not.hpp>
- #include <boost/iterator/iterator_facade.hpp>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/is_reference.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #include <boost/range/detail/any_iterator_buffer.hpp>
- #include <boost/range/detail/any_iterator_interface.hpp>
- #include <boost/range/detail/any_iterator_wrapper.hpp>
- #include <boost/utility/enable_if.hpp>
- namespace boost
- {
- namespace range_detail
- {
- // metafunction to determine if T is a const reference
- template<class T>
- struct is_const_reference
- {
- typedef typename mpl::and_<
- typename is_reference<T>::type,
- typename is_const<
- typename remove_reference<T>::type
- >::type
- >::type type;
- };
- // metafunction to determine if T is a mutable reference
- template<class T>
- struct is_mutable_reference
- {
- typedef typename mpl::and_<
- typename is_reference<T>::type,
- typename mpl::not_<
- typename is_const<
- typename remove_reference<T>::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<class SourceReference, class TargetReference>
- struct is_convertible_to_value_as_reference
- {
- typedef typename mpl::and_<
- typename mpl::not_<
- typename is_reference<TargetReference>::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<class SomeIterator>
- struct is_any_iterator
- : mpl::bool_<false>
- {
- };
- // 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_<true>
- {
- };
- } // namespace range_detail
- namespace iterators
- {
- 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<any_iterator_type>::iterator_category iterator_category;
- typedef Difference difference_type;
- typedef typename iterator_pointer<any_iterator_type>::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<any_iterator_type>::iterator_category iterator_category;
- typedef Difference difference_type;
- typedef typename iterator_pointer<any_iterator_type>::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 <class T>
- 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 <class T>
- 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 detail
- } //namespace iterators
- 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 ::boost::enable_if<
- typename mpl::and_<
- typename is_mutable_reference<OtherReference>::type,
- typename is_const_reference<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 ::boost::enable_if<
- typename mpl::or_<
- typename mpl::and_<
- typename is_mutable_reference<OtherReference>::type,
- typename is_mutable_reference<Reference>::type
- >::type,
- typename mpl::and_<
- typename is_const_reference<OtherReference>::type,
- typename is_const_reference<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 ::boost::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<class WrappedIterator>
- explicit any_iterator(
- const WrappedIterator& wrapped_iterator,
- typename disable_if<
- typename is_any_iterator<WrappedIterator>::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 implementation 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
|