Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2003-08-13 08:12:47


Raoul Gough <yg-boost-users_at_[hidden]> writes:

> I have a situation where I want to specialize a class template on the
> basis of iterator_category, but I don't see how to get one of the
> standard categories when passed a boost iterator adapter. Currently,
> std::iterator_traits<MyIter>::iterator_category is giving me:
>
> boost::iterator_tag<boost::writable_lvalue_iterator_tag
> , boost::random_access_traversal_tag>
>
> I need random_access_iterator_tag for the right specialization to
> happen. Is there any way to get the *standard* iterator category from
> a boost iterator?
>
> MyIter is boost::indirect_iterator<std::vector<int *>::iterator>
> compiler is gcc 3.2.3 (mingw special 20030504-1)
>
> BTW, isn't this non-standard iterator_category bound to cause
> problems? e.g. if I use std::distance (MyIter(), MyIter()), how does
> the compiler know that it should use the
> std::random_access_iterator_tag specialization of std::distance?

Does your standard library really have a *specialization*? Most
libraries use tag dispatching to discriminate categories - it works
nicely with the inheritance structure of existing categories.
Technically, you are right - a standard library is allowed to use
specialization. AFAIK, none of them do, and we hope that when (if)
our proposal is accepted, tag convertibility will be an acceptable
standards-compliant mechanism. So, while I suggest you avoid
specialization and use tag dispatching instead, if you must do it:

    // True iff T is a tag "derived" from Tag
    template <class Tag, class T>
    struct is_tag
      : mpl::or_<
            is_convertible<T, Tag>

            // Because we can't actually get forward_iterator_tag to
            // derive from input_output_iterator_tag, we need this
            // case.
          , mpl::and_<
                is_convertible<T,std::forward_iterator_tag>
              , is_convertible<detail::input_output_iterator_tag,Tag>
>
>
    {};

    // Helper metafunction for std_category below
    template <class Cat, class Tag, class Next>
    struct match_tag
      : mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
    {
    };

    // Converts a possibly user-defined category tag to the
    // most-derived standard tag which is a base of that tag.
    template <class Category>
    struct std_category
      : match_tag<
            Category, std::random_access_iterator_tag
          , match_tag<Category, std::bidirectional_iterator_tag
              , match_tag<Category, std::forward_iterator_tag
                  , match_tag<Category, std::input_iterator_tag
                      , match_tag<Category, std::output_iterator_tag
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
                          , mpl::identity<void>
# else
                          , void
# endif
>
>
>
>
>
    {
    };

Oops, I just lifted this code from
boost/iterator/iterator_categories.hpp but it's in boost::detail::, so
let your conscience be your guide... ;->

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net