// (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 #include #include #include #include #include #include #include #include #include #include #include #include namespace IteratorTypeErasure { template< class Value, class Traversal, class Reference, class Difference > class any_iterator; namespace detail { /////////////////////////////////////////////////////////////////////// // template struct remove_reference_and_const { typedef typename boost::remove_const< typename boost::remove_reference< typename boost::remove_const< T >::type >::type >::type type; }; /////////////////////////////////////////////////////////////////////// // template struct make_iterator_reference_const { typedef typename boost::mpl::if_< typename boost::is_reference::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::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::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::type, typename boost::iterator_value::type >, boost::is_base_of< typename boost::iterator_value::type, typename boost::iterator_value::type >, boost::is_convertible< typename boost::iterator_value::type, typename boost::iterator_value::type > > > type; }; /////////////////////////////////////////////////////////////////////// // template< class WrappedIterator, class AnyIterator > struct reference_types_erasure_compatible_1 { typedef typename boost::is_convertible< typename boost::iterator_reference::type, typename boost::iterator_reference::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::type >, boost::is_reference< typename boost::iterator_reference::type >, boost::mpl::bool_ >::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::type >, boost::is_reference< typename boost::iterator_reference::type > >, boost::mpl::or_< boost::is_same< typename remove_reference_and_const< typename boost::iterator_reference::type >::type, typename remove_reference_and_const< typename boost::iterator_reference::type >::type >, boost::is_base_of< typename remove_reference_and_const< typename boost::iterator_reference::type >::type, typename remove_reference_and_const< typename boost::iterator_reference::type >::type > >, boost::mpl::bool_ >::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::type, std::output_iterator_tag >, boost::is_convertible< WrappedIterator&, typename boost::iterator_reference::type >, boost::mpl::and_< // WrappedIterator's reference type must convert to AnyIterator's reference type. typename reference_types_erasure_compatible_1::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::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::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::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::type, typename boost::iterator_difference::type >, boost::is_convertible< typename boost::iterator_difference::type, typename boost::iterator_difference::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::type here, // as it does not equal the traversal tag. typename AnyIterator::Traversal, typename boost::iterator_traversal::type >, boost::is_base_of< // Do not use boost::iterator_traversal::type here, // as it does not equal the traversal tag. typename AnyIterator::Traversal, typename boost::iterator_traversal::type > > type; }; /////////////////////////////////////////////////////////////////////// // template< class WrappedIterator, class AnyIterator > struct is_iterator_type_erasure_compatible : public boost::mpl::bool_< boost::mpl::and_< value_types_erasure_compatible, reference_types_erasure_compatible, difference_types_erasure_compatible, traversal_types_erasure_compatible >::value > { }; /////////////////////////////////////////////////////////////////////// // template struct is_any_iterator : public boost::mpl::bool_ { }; // template< class Value, class Traversal, class Reference, class Difference > struct is_any_iterator< any_iterator< Value, Traversal, Reference, Difference > > : public boost::mpl::bool_ { }; } // end namespace detail } // end namespace IteratorTypeErasure #endif // ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP