|
Boost Users : |
Subject: Re: [Boost-users] [mpl] Iterator Concept Checking? SOLVED + Recommendation.
From: Stirling Westrup (swestrup_at_[hidden])
Date: 2010-11-02 21:06:25
On Sun, Oct 31, 2010 at 6:16 PM, Stirling Westrup <swestrup_at_[hidden]> wrote:
> On Sat, Oct 30, 2010 at 8:57 PM, David Abrahams <dave_at_[hidden]> wrote:
>>
>> At Sat, 30 Oct 2010 17:55:35 -0400,
>> Stirling Westrup wrote:
>>>
>>> I am writing some algorithms to operate on MPL sequences, and I would
>>> like to use some form of concept checking to ensure that the types
>>> passed in that are supposed to be iterators are, in fact, iterators.
>>>
I have solved the problem I was working on, but as I'm not completely
happy with my solution, I thought I'd post it here and make a
recommendation for a small change to MPL that would have simplified my
work.
I discovered while reading about the iterator_category metafunction
that the iterator tags had ascending values. (
http://www.boost.org/doc/libs/1_44_0/libs/mpl/doc/refmanual/iterator-category.html
). This is only documented there, and not in the description of the
individual iterator categories. In fact, the individual iterator
categories are completely misleading as they state that there is a
member named 'category' that is convertible to the type of the tag.
Since a random iterator is a refinement of a forward iterator and
therefor has at least the same set of requirements, it would imply
that:
BOOST_MPL_ASSERT
(( is_convertible<RandomIterator::category,forward_iterator_tag>))
should succeed, and it does NOT.
It would seem that one should use iterator_category to determine if
something is an iterator or not, but its only actually defined when
its type is an iterator, so that doesn't really work. I ended up
writing my own version that was defined for all types, like this:
struct non_iterator_tag : mpl::int_<INT_MIN>
{ typedef non_iterator_tag type; };
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_category,category,false)
template<bool b, typename T>
struct category_impl
{
typedef non_iterator_tag type;
static const type::value_type value = type::value;
};
template<typename T>
struct category_impl<true,T>
{
typedef typename mpl::iterator_category<T>::type type;
static const int value = type::value;
};
// just like mpl::iterator_category<T> but can be passed any
// type, and returns mplx::not_iterator_tag on bad types. Note
// that this value will compare less-than any valid iterator
// tag.
template<typename T>
struct category
: category_impl<has_category<T>::value,T>
{};
template<typename Iterator>
struct is_forward_iterator
{
typedef typename mpl::greater_equal
< typename category<Iterator>::type
, mpl::forward_iterator_tag
>::type type;
};
template<typename Iterator>
struct is_bidirectional_iterator
{
typedef typename mpl::greater_equal
< typename category<Iterator>::type
, mpl::bidirectional_iterator_tag
>::type type;
};
template<typename Iterator>
struct is_random_access_iterator
{
typedef typename mpl::greater_equal
< typename category<Iterator>::type
, mpl::random_access_iterator_tag
>::type type;
};
The above works, but it relies upon me testing to see if there is an
embedded category member, which I suspect is going to get deprecated
by iterator_category<> just like all the other members were. It would
be far preferable for me if there was an actual non_iterator_tag and
iterator_category<> were already defined for all types, so it could
both be used in a convenient manner, and so that there was an obvious
way to write a specialization in the case that, for instance, one
needed the type 'int' to be an iterator.
In the very least, please update the documentation to mention the
actual relationships between the tags in the discussion about the
iterators, and to remove the incorrect 'convertible' description.
-- Stirling Westrup Programmer, Entrepreneur. https://www.linkedin.com/e/fpf/77228 http://www.linkedin.com/in/swestrup http://technaut.livejournal.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