eedb/share/any_iterator/detail/any_iterator_metafunctions.hpp
2018-01-26 19:22:40 +01:00

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