3 // Copyright Neil Groves 2010. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org/libs/range/
10 #ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
11 #define BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
13 #include <boost/mpl/and.hpp>
14 #include <boost/mpl/or.hpp>
15 #include <boost/mpl/not.hpp>
16 #include <boost/iterator/iterator_facade.hpp>
17 #include <boost/type_traits/is_const.hpp>
18 #include <boost/type_traits/is_reference.hpp>
19 #include <boost/type_traits/remove_reference.hpp>
20 #include <boost/range/detail/any_iterator_buffer.hpp>
21 #include <boost/range/detail/any_iterator_interface.hpp>
22 #include <boost/range/detail/any_iterator_wrapper.hpp>
23 #include <boost/utility/enable_if.hpp>
27 namespace range_detail
29 // metafunction to determine if T is a const reference
31 struct is_const_reference
33 typedef typename mpl::and_<
34 typename is_reference<T>::type,
36 typename remove_reference<T>::type
41 // metafunction to determine if T is a mutable reference
43 struct is_mutable_reference
45 typedef typename mpl::and_<
46 typename is_reference<T>::type,
49 typename remove_reference<T>::type
55 // metafunction to evaluate if a source 'reference' can be
56 // converted to a target 'reference' as a value.
58 // This is true, when the target reference type is actually
59 // not a reference, and the source reference is convertible
60 // to the target type.
61 template<class SourceReference, class TargetReference>
62 struct is_convertible_to_value_as_reference
64 typedef typename mpl::and_<
66 typename is_reference<TargetReference>::type
68 , typename is_convertible<
80 , class Buffer = any_iterator_default_buffer
84 // metafunction to determine if SomeIterator is an
87 // This is the general implementation which evaluates to false.
88 template<class SomeIterator>
89 struct is_any_iterator
94 // specialization of is_any_iterator to return true for
95 // any_iterator classes regardless of template parameters.
103 struct is_any_iterator<
115 } // namespace range_detail
122 // These are specialized since the iterator_facade versions lack
123 // the requisite typedefs to allow wrapping to determine the types
124 // if a user copy constructs from a postfix increment.
133 class postfix_increment_proxy<
134 range_detail::any_iterator<
143 typedef range_detail::any_iterator<
152 typedef Value value_type;
153 typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
154 typedef Difference difference_type;
155 typedef typename iterator_pointer<any_iterator_type>::type pointer;
156 typedef Reference reference;
158 explicit postfix_increment_proxy(any_iterator_type const& x)
165 return this->stored_value;
168 mutable value_type stored_value;
178 class writable_postfix_increment_proxy<
179 range_detail::any_iterator<
188 typedef range_detail::any_iterator<
196 typedef Value value_type;
197 typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
198 typedef Difference difference_type;
199 typedef typename iterator_pointer<any_iterator_type>::type pointer;
200 typedef Reference reference;
202 explicit writable_postfix_increment_proxy(any_iterator_type const& x)
207 // Dereferencing must return a proxy so that both *r++ = o and
208 // value_type(*r++) can work. In this case, *r is the same as
209 // *r++, and the conversion operator below is used to ensure
211 writable_postfix_increment_proxy const&
217 // Provides readability of *r++
218 operator value_type&() const
223 // Provides writability of *r++
225 T const& operator=(T const& x) const
227 *this->stored_iterator = x;
231 // This overload just in case only non-const objects are writable
233 T& operator=(T& x) const
235 *this->stored_iterator = x;
240 operator any_iterator_type const&() const
242 return stored_iterator;
246 mutable value_type stored_value;
247 any_iterator_type stored_iterator;
251 } //namespace iterators
253 namespace range_detail
263 : public iterator_facade<
279 , class OtherTraversal
280 , class OtherReference
281 , class OtherDifference
284 friend class any_iterator;
289 typedef typename any_iterator_interface_type_generator<
294 >::type abstract_base_type;
296 typedef iterator_facade<
310 typedef Buffer buffer_type;
313 typedef typename base_type::value_type value_type;
314 typedef typename base_type::reference reference;
315 typedef typename base_type::difference_type difference_type;
317 // Default constructor
321 // Simple copy construction without conversion
322 any_iterator(const any_iterator& other)
324 , m_impl(other.m_impl
325 ? other.m_impl->clone(m_buffer)
330 // Simple assignment operator without conversion
331 any_iterator& operator=(const any_iterator& other)
336 m_impl->~abstract_base_type();
337 m_buffer.deallocate();
340 m_impl = other.m_impl->clone(m_buffer);
345 // Implicit conversion from another any_iterator where the
346 // conversion is from a non-const reference to a const reference
349 , class OtherTraversal
350 , class OtherReference
351 , class OtherDifference
353 any_iterator(const any_iterator<
360 typename ::boost::enable_if<
362 typename is_mutable_reference<OtherReference>::type,
363 typename is_const_reference<Reference>::type
368 : m_impl(other.m_impl
369 ? other.m_impl->clone_const_ref(m_buffer)
375 // Implicit conversion from another any_iterator where the
376 // reference types of the source and the target are references
377 // that are either both const, or both non-const.
380 , class OtherTraversal
381 , class OtherReference
382 , class OtherDifference
384 any_iterator(const any_iterator<
391 typename ::boost::enable_if<
394 typename is_mutable_reference<OtherReference>::type,
395 typename is_mutable_reference<Reference>::type
398 typename is_const_reference<OtherReference>::type,
399 typename is_const_reference<Reference>::type
405 : m_impl(other.m_impl
406 ? other.m_impl->clone(m_buffer)
412 // Implicit conversion to an any_iterator that uses a value for
413 // the reference type.
416 , class OtherTraversal
417 , class OtherReference
418 , class OtherDifference
420 any_iterator(const any_iterator<
427 typename ::boost::enable_if<
428 typename is_convertible_to_value_as_reference<
435 : m_impl(other.m_impl
436 ? other.m_impl->clone_reference_as_value(m_buffer)
442 any_iterator clone() const
446 result.m_impl = m_impl->clone(result.m_buffer);
453 , typename abstract_base_type::const_reference
457 clone_const_ref() const
459 typedef any_iterator<
462 , typename abstract_base_type::const_reference
470 result.m_impl = m_impl->clone_const_ref(result.m_buffer);
475 // implicit conversion and construction from type-erasure-compatible
477 template<class WrappedIterator>
478 explicit any_iterator(
479 const WrappedIterator& wrapped_iterator,
481 typename is_any_iterator<WrappedIterator>::type
486 typedef typename any_iterator_wrapper_type_generator<
492 >::type wrapper_type;
494 void* ptr = m_buffer.allocate(sizeof(wrapper_type));
495 m_impl = new(ptr) wrapper_type(wrapped_iterator);
500 // manually run the destructor, the deallocation is automatically
501 // handled by the any_iterator_small_buffer base class.
503 m_impl->~abstract_base_type();
507 friend class ::boost::iterator_core_access;
509 Reference dereference() const
511 BOOST_ASSERT( m_impl );
512 return m_impl->dereference();
515 bool equal(const any_iterator& other) const
517 return (m_impl == other.m_impl)
518 || (m_impl && other.m_impl && m_impl->equal(*other.m_impl));
523 BOOST_ASSERT( m_impl );
529 BOOST_ASSERT( m_impl );
533 Difference distance_to(const any_iterator& other) const
535 return m_impl && other.m_impl
536 ? m_impl->distance_to(*other.m_impl)
540 void advance(Difference offset)
542 BOOST_ASSERT( m_impl );
543 m_impl->advance(offset);
546 any_iterator& swap(any_iterator& other)
548 BOOST_ASSERT( this != &other );
549 // grab a temporary copy of the other iterator
550 any_iterator tmp(other);
552 // deallocate the other iterator, taking care to obey the
553 // class-invariants in-case of exceptions later
556 other.m_impl->~abstract_base_type();
557 other.m_buffer.deallocate();
561 // If this is a non-null iterator then we need to put
562 // a clone of this iterators implementation into the other
564 // We can't just swap because of the small buffer optimization.
567 other.m_impl = m_impl->clone(other.m_buffer);
568 m_impl->~abstract_base_type();
569 m_buffer.deallocate();
573 // assign to this instance a clone of the temporarily held
574 // tmp which represents the input other parameter at the
575 // start of execution of this function.
577 m_impl = tmp.m_impl->clone(m_buffer);
582 buffer_type m_buffer;
583 abstract_base_type* m_impl;
586 } // namespace range_detail
589 #endif // include guard