364 lines
12 KiB
C++
364 lines
12 KiB
C++
// (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and
|
|
// distribute this software is granted provided this copyright notice appears
|
|
// in all copies. This software is provided "as is" without express or implied
|
|
// warranty, and with no claim as to its suitability for any purpose.
|
|
|
|
// File Name
|
|
// =========
|
|
//
|
|
// metafunctions.h
|
|
|
|
// Description
|
|
// ===========
|
|
//
|
|
// Metafunctions for any_iterator
|
|
|
|
#ifndef ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP
|
|
#define ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP
|
|
|
|
// Revision History
|
|
// ================
|
|
//
|
|
// 27 Dec 2006 (Thomas Becker) Created
|
|
|
|
// Includes
|
|
// ========
|
|
#include <boost/iterator/iterator_categories.hpp>
|
|
#include <boost/iterator/iterator_traits.hpp>
|
|
#include <boost/type_traits/remove_const.hpp>
|
|
#include <boost/type_traits/remove_reference.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <boost/type_traits/is_base_of.hpp>
|
|
#include <boost/type_traits/is_convertible.hpp>
|
|
#include <boost/type_traits/is_reference.hpp>
|
|
#include <boost/type_traits/is_pointer.hpp>
|
|
#include <boost/mpl/bool.hpp>
|
|
#include <boost/mpl/and.hpp>
|
|
#include <boost/mpl/or.hpp>
|
|
#include <boost/mpl/not.hpp>
|
|
|
|
namespace IteratorTypeErasure
|
|
{
|
|
|
|
template<
|
|
class Value,
|
|
class Traversal,
|
|
class Reference,
|
|
class Difference
|
|
>
|
|
class any_iterator;
|
|
|
|
namespace detail
|
|
{
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<typename T>
|
|
struct remove_reference_and_const
|
|
{
|
|
typedef typename boost::remove_const<
|
|
typename boost::remove_reference<
|
|
typename boost::remove_const<
|
|
T
|
|
>::type
|
|
>::type
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<typename IteratorReference>
|
|
struct make_iterator_reference_const
|
|
{
|
|
typedef typename boost::mpl::if_<
|
|
typename boost::is_reference<IteratorReference>::type,
|
|
typename boost::remove_const<
|
|
typename boost::remove_reference<
|
|
typename boost::remove_const<
|
|
IteratorReference
|
|
>::type
|
|
>::type
|
|
>::type const &,
|
|
typename boost::remove_const<
|
|
typename boost::remove_reference<
|
|
typename boost::remove_const<
|
|
IteratorReference
|
|
>::type
|
|
>::type
|
|
>::type const
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct value_types_erasure_compatible
|
|
{
|
|
// Really, we just want WrappedIterator's value_type to convert to
|
|
// AnyIterator's value_type. But many real world output iterators
|
|
// define their value_type as void. Therefore, we simply ignore
|
|
// the value type for output iterators. That's fine because for
|
|
// output iterators, the relevant type erasure information is all
|
|
// in the reference type.
|
|
|
|
typedef typename boost::mpl::or_<
|
|
boost::is_same<
|
|
typename boost::iterator_category<WrappedIterator>::type,
|
|
std::output_iterator_tag
|
|
>,
|
|
|
|
// Really, we just want WrappedIterator's value_type to convert to
|
|
// AnyIterator's value_type. But we need to work around a flaw in
|
|
// boost::is_convertible. boost::is_convertible<X, Y>::value is
|
|
// false whenever X and Y are abstract base classes (even when X
|
|
// and Y are the same). This will be fixed in C++ concepts.
|
|
boost::mpl::or_<
|
|
boost::is_same<
|
|
typename boost::iterator_value<WrappedIterator>::type,
|
|
typename boost::iterator_value<AnyIterator>::type
|
|
>,
|
|
boost::is_base_of<
|
|
typename boost::iterator_value<AnyIterator>::type,
|
|
typename boost::iterator_value<WrappedIterator>::type
|
|
>,
|
|
boost::is_convertible<
|
|
typename boost::iterator_value<WrappedIterator>::type,
|
|
typename boost::iterator_value<AnyIterator>::type
|
|
>
|
|
>
|
|
> type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct reference_types_erasure_compatible_1
|
|
{
|
|
typedef typename boost::is_convertible<
|
|
typename boost::iterator_reference<WrappedIterator>::type,
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct reference_types_erasure_compatible_2
|
|
{
|
|
typedef typename boost::mpl::if_<
|
|
boost::is_reference<
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>,
|
|
boost::is_reference<
|
|
typename boost::iterator_reference<WrappedIterator>::type
|
|
>,
|
|
boost::mpl::bool_<true>
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct reference_types_erasure_compatible_3
|
|
{
|
|
|
|
typedef typename boost::mpl::if_<
|
|
boost::mpl::and_<
|
|
boost::is_reference<
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>,
|
|
boost::is_reference<
|
|
typename boost::iterator_reference<WrappedIterator>::type
|
|
>
|
|
>,
|
|
boost::mpl::or_<
|
|
boost::is_same<
|
|
typename remove_reference_and_const<
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>::type,
|
|
typename remove_reference_and_const<
|
|
typename boost::iterator_reference<WrappedIterator>::type
|
|
>::type
|
|
>,
|
|
boost::is_base_of<
|
|
typename remove_reference_and_const<
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>::type,
|
|
typename remove_reference_and_const<
|
|
typename boost::iterator_reference<WrappedIterator>::type
|
|
>::type
|
|
>
|
|
>,
|
|
boost::mpl::bool_<true>
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct reference_types_erasure_compatible
|
|
{
|
|
// Output iterators are weird. Many real world output iterators
|
|
// define their reference type as void. In the world of boost
|
|
// iterators, that's terribly wrong, because in that world, an
|
|
// iterator's reference type is always the result type of
|
|
// operator* (and that makes very good sense, too). Therefore,
|
|
// when WrappedIterator is an output iterator, we use
|
|
// WrappedIterator& for WrappedIterator's reference type,
|
|
// because that's the real, true reference type. Moreover,
|
|
// we just require that WrappedIterator& convert to AnyIterator's
|
|
// reference type. The other subtleties are not relevant.
|
|
|
|
typedef typename boost::mpl::if_<
|
|
boost::is_same<
|
|
typename boost::iterator_category<WrappedIterator>::type,
|
|
std::output_iterator_tag
|
|
>,
|
|
boost::is_convertible<
|
|
WrappedIterator&,
|
|
typename boost::iterator_reference<AnyIterator>::type
|
|
>,
|
|
boost::mpl::and_<
|
|
|
|
// WrappedIterator's reference type must convert to AnyIterator's reference type.
|
|
typename reference_types_erasure_compatible_1<WrappedIterator, AnyIterator>::type,
|
|
|
|
// If AnyIterator's reference type is a reference, then the
|
|
// same must be true for WrappedIterator's reference type.
|
|
typename reference_types_erasure_compatible_2<WrappedIterator, AnyIterator>::type,
|
|
|
|
// If AnyIterator's reference type and WrappedIterator's
|
|
// reference type are both references, then one of the
|
|
// following must hold:
|
|
//
|
|
// 1) AnyIterator's reference type and WrappedIterator's
|
|
// reference type are the same.
|
|
//
|
|
// 2) AnyIterator's reference type is a base class of WrappedIterator's
|
|
// reference type.
|
|
//
|
|
typename reference_types_erasure_compatible_3<WrappedIterator, AnyIterator>::type
|
|
>
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct difference_types_erasure_compatible
|
|
{
|
|
|
|
// Difference type matters only for random access iterators.
|
|
|
|
typedef typename boost::mpl::or_<
|
|
boost::mpl::not_<
|
|
boost::is_same<
|
|
// Do not use boost::iterator_traversal<AnyIterator>::type here,
|
|
// as it does not equal the traversal tag.
|
|
typename AnyIterator::Traversal,
|
|
boost::random_access_traversal_tag
|
|
>
|
|
>,
|
|
boost::mpl::and_<
|
|
boost::is_convertible<
|
|
typename boost::iterator_difference<WrappedIterator>::type,
|
|
typename boost::iterator_difference<AnyIterator>::type
|
|
>,
|
|
boost::is_convertible<
|
|
typename boost::iterator_difference<AnyIterator>::type,
|
|
typename boost::iterator_difference<WrappedIterator>::type
|
|
>
|
|
>
|
|
> type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct traversal_types_erasure_compatible
|
|
{
|
|
typedef typename boost::mpl::or_<
|
|
boost::is_same<
|
|
// Do not use boost::iterator_traversal<AnyIterator>::type here,
|
|
// as it does not equal the traversal tag.
|
|
typename AnyIterator::Traversal,
|
|
typename boost::iterator_traversal<WrappedIterator>::type
|
|
>,
|
|
boost::is_base_of<
|
|
// Do not use boost::iterator_traversal<AnyIterator>::type here,
|
|
// as it does not equal the traversal tag.
|
|
typename AnyIterator::Traversal,
|
|
typename boost::iterator_traversal<WrappedIterator>::type
|
|
>
|
|
> type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<
|
|
class WrappedIterator,
|
|
class AnyIterator
|
|
>
|
|
struct is_iterator_type_erasure_compatible :
|
|
public boost::mpl::bool_<
|
|
boost::mpl::and_<
|
|
value_types_erasure_compatible<WrappedIterator, AnyIterator>,
|
|
reference_types_erasure_compatible<WrappedIterator, AnyIterator>,
|
|
difference_types_erasure_compatible<WrappedIterator, AnyIterator>,
|
|
traversal_types_erasure_compatible<WrappedIterator, AnyIterator>
|
|
>::value
|
|
>
|
|
{
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
template<class SomeIterator>
|
|
struct is_any_iterator : public boost::mpl::bool_<false>
|
|
{
|
|
};
|
|
//
|
|
template<
|
|
class Value,
|
|
class Traversal,
|
|
class Reference,
|
|
class Difference
|
|
>
|
|
struct is_any_iterator<
|
|
any_iterator<
|
|
Value,
|
|
Traversal,
|
|
Reference,
|
|
Difference
|
|
>
|
|
> : public boost::mpl::bool_<true>
|
|
{
|
|
};
|
|
|
|
} // end namespace detail
|
|
|
|
} // end namespace IteratorTypeErasure
|
|
|
|
#endif // ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP
|