forked from boostorg/range
[range] - merge the tested changes from the trunk in preparation for the 1.46 release.
[SVN r67905]
This commit is contained in:
587
include/boost/range/detail/any_iterator.hpp
Normal file
587
include/boost/range/detail/any_iterator.hpp
Normal file
@ -0,0 +1,587 @@
|
||||
// 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/cast.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/not.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>
|
||||
|
||||
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 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 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<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 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 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 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
|
Reference in New Issue
Block a user