Made implementation work, if is_convertible

is not supported.
Moved categories in new detail header.
Introduced category detection metafunctions.


[SVN r829]
This commit is contained in:
Thomas Witt
2003-01-02 17:52:51 +00:00
parent b97ad86e9c
commit d5819a1b16
2 changed files with 367 additions and 39 deletions

View File

@@ -0,0 +1,318 @@
// (C) Copyright Thomas Witt 2002. 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.
#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
#define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool_c.hpp>
#include <boost/mpl/logical/or.hpp>
#include <iterator>
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
#endif
namespace boost {
// Return Type Categories
struct readable_iterator_tag { };
struct writable_iterator_tag { };
struct swappable_iterator_tag :
virtual public readable_iterator_tag, // Not sure about this change -JGS
virtual public writable_iterator_tag { };
struct constant_lvalue_iterator_tag :
virtual public readable_iterator_tag { };
struct mutable_lvalue_iterator_tag :
virtual public swappable_iterator_tag,
virtual public constant_lvalue_iterator_tag { };
// Traversal Categories
struct input_traversal_tag { };
struct output_traversal_tag { };
struct forward_traversal_tag : virtual public input_traversal_tag,
virtual public output_traversal_tag { };
struct bidirectional_traversal_tag : virtual public forward_traversal_tag { };
struct random_access_traversal_tag : virtual public bidirectional_traversal_tag { };
struct error_iterator_tag { };
namespace detail
{
//
// Tag detection meta functions
//
// Needed to work with compilers
// without working is_convertible
//
#ifndef BOOST_NO_IS_CONVERTIBLE
template <class Category>
struct is_input_iterator :
is_convertible<Category*, std::input_iterator_tag*>
{
};
template <class Category>
struct is_output_iterator :
is_convertible<Category*, std::output_iterator_tag*>
{
};
template <class Category>
struct is_forward_iterator :
is_convertible<Category*, std::forward_iterator_tag*>
{
};
template <class Category>
struct is_bidirectional_iterator :
is_convertible<Category*, std::bidirectional_iterator_tag*>
{
};
template <class Category>
struct is_random_access_iterator :
is_convertible<Category*, std::random_access_iterator_tag*>
{
};
template <class Category>
struct is_readable_iterator :
is_convertible<Category*, readable_iterator_tag*>
{ };
template <class Category>
struct is_writable_iterator :
is_convertible<Category*, writable_iterator_tag*>
{ };
template <class Category>
struct is_swappable_iterator :
is_convertible<Category*, swappable_iterator_tag*>
{ };
template <class Category>
struct is_constant_lvalue_iterator :
is_convertible<Category*, constant_lvalue_iterator_tag*>
{ };
template <class Category>
struct is_mutable_lvalue_iterator :
is_convertible<Category*, mutable_lvalue_iterator_tag*>
{ };
template <class Category>
struct is_input_traversal_iterator :
is_convertible<Category*, input_traversal_tag*>
{ };
template <class Category>
struct is_output_traversal_iterator :
is_convertible<Category*, output_traversal_tag*>
{ };
template <class Category>
struct is_forward_traversal_iterator :
is_convertible<Category*, forward_traversal_tag*>
{ };
template <class Category>
struct is_bidirectional_traversal_iterator :
is_convertible<Category*, bidirectional_traversal_tag*>
{ };
template <class Category>
struct is_random_access_traversal_iterator :
is_convertible<Category*, random_access_traversal_tag*>
{ };
#else
//
// We cannot detect the iterator category for custom
// tag types. For custom tag types false_c is returned
//
// As a result the std iterator category detection functions
// can't detect the iterator category of the new iterator_tag template.
//
//
// std iterator categories
//
template <class Category>
struct is_random_access_iterator :
mpl::false_c
{};
template <>
struct is_random_access_iterator<std::random_access_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_bidirectional_iterator :
is_random_access_iterator< Category >
{};
template <>
struct is_bidirectional_iterator<std::bidirectional_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_forward_iterator :
is_bidirectional_iterator< Category >
{};
template <>
struct is_forward_iterator<std::forward_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_output_iterator :
is_forward_iterator< Category >
{};
template <>
struct is_output_iterator<std::output_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_input_iterator :
is_forward_iterator< Category >
{};
template <>
struct is_input_iterator<std::input_iterator_tag> :
mpl::true_c
{};
//
// Return type
//
template <class Category>
struct is_mutable_lvalue_iterator :
mpl::false_c
{};
template <>
struct is_mutable_lvalue_iterator<mutable_lvalue_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_constant_lvalue_iterator :
is_mutable_lvalue_iterator<Category>
{};
template <>
struct is_constant_lvalue_iterator<constant_lvalue_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_swappable_iterator :
is_constant_lvalue_iterator<Category>
{};
template <>
struct is_swappable_iterator<swappable_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_readable_iterator :
mpl::logical_or< is_swappable_iterator<Category>,
is_constant_lvalue_iterator<Category> >
{};
template <>
struct is_readable_iterator<readable_iterator_tag> :
mpl::true_c
{};
template <class Category>
struct is_writable_iterator :
is_swappable_iterator<Category>
{};
template <>
struct is_writable_iterator<writable_iterator_tag> :
mpl::true_c
{};
//
// Traversal
//
template <class Category>
struct is_random_access_traversal_iterator :
mpl::false_c
{};
template <>
struct is_random_access_traversal_iterator<random_access_traversal_tag> :
mpl::true_c
{};
template <class Category>
struct is_bidirectional_traversal_iterator :
is_random_access_traversal_iterator< Category >
{};
template <>
struct is_bidirectional_traversal_iterator<bidirectional_traversal_tag> :
mpl::true_c
{};
template <class Category>
struct is_forward_traversal_iterator :
is_bidirectional_traversal_iterator< Category >
{};
template <>
struct is_forward_traversal_iterator<forward_traversal_tag> :
mpl::true_c
{};
template <class Category>
struct is_input_traversal_iterator :
is_forward_traversal_iterator< Category >
{};
template <>
struct is_input_traversal_iterator<input_traversal_tag> :
mpl::true_c
{};
template <class Category>
struct is_output_traversal_iterator :
is_forward_traversal_iterator< Category >
{};
template <>
struct is_output_traversal_iterator<output_traversal_tag> :
mpl::true_c
{};
#endif
} // namespace detail
} // namespace boost
#ifdef BOOST_NO_IS_CONVERTIBLE
# undef BOOST_NO_IS_CONVERTIBLE
#endif
#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP

View File

@@ -11,41 +11,26 @@
#define BOOST_ITERATOR_CATEGORIES_HPP #define BOOST_ITERATOR_CATEGORIES_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/iterator/detail/categories.hpp>
#include <boost/type_traits/conversion_traits.hpp> #include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/cv_traits.hpp> #include <boost/type_traits/cv_traits.hpp>
#include <boost/detail/iterator.hpp> #include <boost/detail/iterator.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/apply_if.hpp> #include <boost/mpl/apply_if.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/mpl/bool_c.hpp> #include <boost/mpl/bool_c.hpp>
#include <boost/mpl/aux_/has_xxx.hpp> #include <boost/mpl/aux_/has_xxx.hpp>
#include <boost/mpl/logical/not.hpp>
#include <boost/mpl/logical/or.hpp> #include <boost/mpl/logical/or.hpp>
#include <boost/mpl/logical/and.hpp> #include <boost/mpl/logical/and.hpp>
#include <iterator> #include <iterator>
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
#endif
namespace boost { namespace boost {
// Return Type Categories
struct readable_iterator_tag { };
struct writable_iterator_tag { };
struct swappable_iterator_tag :
virtual public readable_iterator_tag, // Not sure about this change -JGS
virtual public writable_iterator_tag { };
struct constant_lvalue_iterator_tag :
virtual public readable_iterator_tag { };
struct mutable_lvalue_iterator_tag :
virtual public swappable_iterator_tag,
virtual public constant_lvalue_iterator_tag { };
// Traversal Categories
struct input_traversal_tag { };
struct output_traversal_tag { };
struct forward_traversal_tag : virtual public input_traversal_tag,
virtual public output_traversal_tag { };
struct bidirectional_traversal_tag : virtual public forward_traversal_tag { };
struct random_access_traversal_tag : virtual public bidirectional_traversal_tag { };
struct error_iterator_tag { };
// When creating new iterators, you have three options. // When creating new iterators, you have three options.
// 1) The recommended option is to specialize the return_category // 1) The recommended option is to specialize the return_category
@@ -85,13 +70,13 @@ namespace boost {
template <typename Category, typename ValueType> template <typename Category, typename ValueType>
struct iter_category_to_return struct iter_category_to_return
: mpl::if_< : mpl::if_<
is_convertible<Category*, std::forward_iterator_tag*> is_forward_iterator<Category>
, typename choose_lvalue_return<ValueType>::type , typename choose_lvalue_return<ValueType>::type
, typename mpl::if_< , typename mpl::if_<
is_convertible<Category*, std::input_iterator_tag*> is_input_iterator<Category>
, boost::readable_iterator_tag , boost::readable_iterator_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<Category*, std::output_iterator_tag*> is_output_iterator<Category>
, boost::writable_iterator_tag , boost::writable_iterator_tag
, boost::error_iterator_tag , boost::error_iterator_tag
>::type >::type
@@ -103,16 +88,16 @@ namespace boost {
template <typename Category> template <typename Category>
struct iter_category_to_traversal struct iter_category_to_traversal
: mpl::if_< : mpl::if_<
is_convertible<Category*, std::random_access_iterator_tag*> is_random_access_iterator<Category>
, random_access_traversal_tag , random_access_traversal_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<Category*, std::bidirectional_iterator_tag*> is_bidirectional_iterator<Category>
, bidirectional_traversal_tag , bidirectional_traversal_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<Category*, std::forward_iterator_tag*> is_forward_iterator<Category>
, forward_traversal_tag , forward_traversal_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<Category*, std::input_iterator_tag*> is_input_iterator<Category>
, input_traversal_tag , input_traversal_tag
, output_traversal_tag , output_traversal_tag
>::type >::type
@@ -122,6 +107,23 @@ namespace boost {
{ {
}; };
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
//
// has_traversal fails for cwpro7, so we have to use
// something less sophisticated.
//
// The solution depends on the fact that only
// std iterator categories work with is_xxx_iterator
// meta functions, as BOOST_NO_IS_CONVERTIBLE is
// defined for cwpro7.
//
template <class Tag>
struct is_new_iterator_tag :
mpl::logical_and< mpl::logical_not< is_input_iterator<Tag> >,
mpl::logical_not< is_output_iterator<Tag> > >
{};
#else
BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal) BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal)
template <class Tag> template <class Tag>
@@ -133,6 +135,9 @@ namespace boost {
, mpl::bool_c<false> >::type , mpl::bool_c<false> >::type
{ {
}; };
#endif
} // namespace detail } // namespace detail
namespace detail { namespace detail {
@@ -202,21 +207,23 @@ namespace boost {
#endif #endif
// TODO Fix this for BOOST_NO_IS_CONVERTIBLE
template <class RC, class TC> template <class RC, class TC>
struct cvt_iterator_category struct cvt_iterator_category
: mpl::if_< : mpl::if_<
mpl::logical_or< mpl::logical_or<
is_convertible<RC*, mutable_lvalue_iterator_tag*> detail::is_mutable_lvalue_iterator<RC>
, is_convertible<RC*, constant_lvalue_iterator_tag*> , detail::is_constant_lvalue_iterator<RC>
> >
, typename mpl::if_< , typename mpl::if_<
is_convertible<TC*, random_access_traversal_tag*> detail::is_random_access_traversal_iterator<TC>
, std::random_access_iterator_tag , std::random_access_iterator_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<TC*, bidirectional_traversal_tag*> detail::is_bidirectional_traversal_iterator<TC>
, std::bidirectional_iterator_tag , std::bidirectional_iterator_tag
, typename mpl::if_< , typename mpl::if_<
is_convertible<TC*, forward_traversal_tag*> detail::is_forward_traversal_iterator<TC>
, std::forward_iterator_tag , std::forward_iterator_tag
, error_iterator_tag , error_iterator_tag
>::type >::type
@@ -225,14 +232,14 @@ namespace boost {
, typename mpl::if_< , typename mpl::if_<
mpl::logical_and< mpl::logical_and<
is_convertible<RC*, readable_iterator_tag*> detail::is_readable_iterator<RC>
, is_convertible<TC*, input_traversal_tag*> , detail::is_input_traversal_iterator<TC>
> >
, std::input_iterator_tag , std::input_iterator_tag
, typename mpl::if_< , typename mpl::if_<
mpl::logical_and< mpl::logical_and<
is_convertible<RC*, writable_iterator_tag*> detail::is_writable_iterator<RC>
, is_convertible<TC*, output_traversal_tag*> , detail::is_output_traversal_iterator<TC>
> >
, std::output_iterator_tag , std::output_iterator_tag
, error_iterator_tag , error_iterator_tag
@@ -249,7 +256,10 @@ namespace boost {
typedef TraversalTag traversal; typedef TraversalTag traversal;
}; };
} // namespace boost } // namespace boost
#ifdef BOOST_NO_IS_CONVERTIBLE
# undef BOOST_NO_IS_CONVERTIBLE
#endif
#endif // BOOST_ITERATOR_CATEGORIES_HPP #endif // BOOST_ITERATOR_CATEGORIES_HPP