Improved category handling in iterator_adaptor.

[SVN r19231]
This commit is contained in:
Thomas Witt 2003-07-20 19:18:40 +00:00
parent 3fe0d4b532
commit ed8c60c20b
6 changed files with 90 additions and 27 deletions

View File

@ -329,6 +329,25 @@ namespace boost
template <> struct minimum_category<int, int> { typedef minimum_category type; }; template <> struct minimum_category<int, int> { typedef minimum_category type; };
# endif # endif
//
// Tag classification for use in iterator_adaptor
//
template <class Tag>
struct is_access_tag
: mpl::or_<
is_tag<readable_iterator_tag, Tag>
, mpl::or_<
is_tag<writable_iterator_tag, Tag>
, is_tag<swappable_iterator_tag, Tag>
>
>
{};
template <class Tag>
struct is_traversal_tag
: is_tag<incrementable_traversal_tag, Tag>
{};
} // namespace detail } // namespace detail
} // namespace boost } // namespace boost

View File

@ -15,34 +15,25 @@
namespace boost namespace boost
{ {
namespace detail
{
template <class Iterator>
struct filter_iterator_category
{
typedef iterator_tag<
typename access_category<Iterator>::type
, typename minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> type;
};
} // namespace detail
template <class Predicate, class Iterator> template <class Predicate, class Iterator>
class filter_iterator class filter_iterator
: public iterator_adaptor< : public iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator filter_iterator<Predicate, Iterator>, Iterator
, use_default , use_default
, typename detail::filter_iterator_category<Iterator>::type , typename detail::minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> >
{ {
typedef iterator_adaptor< typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator filter_iterator<Predicate, Iterator>, Iterator
, use_default , use_default
, typename detail::filter_iterator_category<Iterator>::type , typename detail::minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> super_t; > super_t;
friend class iterator_core_access; friend class iterator_core_access;

View File

@ -148,9 +148,18 @@ namespace boost
> >
struct iterator_adaptor_base struct iterator_adaptor_base
{ {
private: // intermediate results private: // intermediate results
typedef typename detail::ia_dflt_help<
Category, BOOST_ITERATOR_CATEGORY<Base> typedef typename mpl::apply_if<
mpl::or_<
is_same<Category, use_default>
, mpl::or_<
is_access_tag<Category>
, is_traversal_tag<Category>
>
>
, BOOST_ITERATOR_CATEGORY<Base>
, mpl::identity<Category>
>::type category; >::type category;
typedef typename detail::ia_dflt_help< typedef typename detail::ia_dflt_help<
@ -170,9 +179,17 @@ namespace boost
Value, iterator_value<Base> Value, iterator_value<Base>
>::type >::type
, typename access_category_tag<category, reference>::type , typename mpl::apply_if<
is_access_tag<Category>
, typename traversal_category_tag<category>::type , mpl::identity<Category>
, access_category_tag<category, reference>
>::type
, typename mpl::apply_if<
is_traversal_tag<Category>
, mpl::identity<Category>
, traversal_category_tag<category>
>::type
, reference , reference

View File

@ -90,10 +90,7 @@ namespace boost
transform_iterator<UnaryFunction, Iterator, Reference, Value> transform_iterator<UnaryFunction, Iterator, Reference, Value>
, Iterator , Iterator
, cv_value_type , cv_value_type
, iterator_tag< , access_category
access_category
, typename traversal_category<Iterator>::type
>
, result_type , result_type
> type; > type;
}; };

View File

@ -112,6 +112,17 @@ public:
{} {}
}; };
// Non-functional iterator for category modification checking
template <class Iter, class Category>
struct modify_category
: boost::iterator_adaptor<
modify_category<Iter, Category>
, Iter
, boost::use_default
, Category
>
{};
template <class T> template <class T>
struct fwd_iterator struct fwd_iterator
: boost::iterator_adaptor< : boost::iterator_adaptor<
@ -221,6 +232,15 @@ main()
test = static_assert_same<BaseIter::iterator_category::access, boost::writable_lvalue_iterator_tag>::value; test = static_assert_same<BaseIter::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<Iter::iterator_category::access, boost::readable_lvalue_iterator_tag>::value; test = static_assert_same<Iter::iterator_category::access, boost::readable_lvalue_iterator_tag>::value;
// Test category modification
typedef modify_category<BaseIter, boost::readable_iterator_tag> ReadableIter;
test = static_assert_same<ReadableIter::iterator_category::access, boost::readable_iterator_tag>::value;
typedef modify_category<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
test = static_assert_same<BaseIter::iterator_category::traversal, boost::random_access_traversal_tag>::value;
test = static_assert_same<IncrementableIter::iterator_category::traversal, boost::incrementable_traversal_tag>::value;
} }
// Test the iterator_adaptor // Test the iterator_adaptor

View File

@ -91,6 +91,25 @@ void category_test()
std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag
>::value; >::value;
BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value));
BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value));
(void)test; (void)test;
} }