Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-08-24 02:36:49


"Alex Chovanec" <achovane_at_[hidden]> writes:

> "David Abrahams" <dave_at_[hidden]> wrote in message
> news:uacwmy7tw.fsf_at_boost-consulting.com...
>> "Alex Chovanec" <achovane_at_[hidden]> writes:
>>
>> >
>> > So 'is_iterator<int *>::value' evaluates to true without generating a
>> > compile error, as it should.
>>
>> *Any* iterator can be implemented the same way. An iterator class
>> does not have to have a value_type member!
>
>
> Ok, you bring up a valid point. I would like to suggest a possible solution
> to this problem, but the explanation is a bit long, so please bear with me.
> :-)
>
> Originally, I was using the following SFINAE approach in 'is_iterator' to
> detect member iterator traits:
>
> template <typename T>
> static char test(
> T *,
> type_tag<typename T::value_type> * = 0,
> type_tag<typename T::reference> * = 0,
> type_tag<typename T::pointer> * = 0,
> type_tag<typename T::difference_type> * = 0,
> type_tag<typename T::iterator_category> * = 0
> );
> static char (& test(...))[2];
>
> I had considered using Boost iterator traits to do the same thing, like
> this:
>
> template <typename T>
> static char test(
> T *,
> type_tag<typename detail::iterator_traits<T>::value_type> * = 0,
> type_tag<typename detail::iterator_traits<T>::reference> * = 0,
> type_tag<typename detail::iterator_traits<T>::pointer> * = 0,
> type_tag<typename detail::iterator_traits<T>::difference_type> * =
> 0,
> type_tag<typename detail::iterator_traits<T>::iterator_category> * =
> 0
> );
> static char (& test(...))[2];
>
> But I felt that the first approach was clearer, and I reasoned that it would
> be ok to rely on member traits if I also defined a partial template
> specialization to handle pointers.
>
> It wasn't until I read your last email that I tried the second approach and
> realized that it doesn't work. It's no surprise that attempting to
> instantiate 'iterator_traits<T>' causes a compile error when 'T' is not an
> iterator, but I had assumed that SFINAE would simply remove this overload of
> 'test' from the set of candidate functions. I see now that SFINAE doesn't
> work unless you have a valid type on the lefthand side of the '::' operator.
>
> So the problem is not that 'iterator_traits<T>::value_type' does not exist;
> the problem is that 'iterator_traits<T>' cannot be instantiated. But what if
> 'iterator_traits<T>' were defined in such a way that it can still be
> instantiated even if 'T' is not an iterator? If 'T' is not an iterator, then
> 'iterator_traits<T>' can simply be defined to be without any member types.
> This is easy to do with a little template metaprogramming.

No it isn't. A valid iterator may have a specialized
std::iterator_traits. We can't change std::iterator_traits.

> The modified
> primary template for Boost iterator traits might look something like this:
>
> template <typename T>
> struct iterator_traits : public
> mpl::if_<
> mpl::or_<
> has_member_iterator_traits<T>,
> is_pointer<T> >,
> std::iterator_traits<T>,
> empty_iterator_traits
> >::type
> {};
>
> Here, 'has_member_iterator_traits' implements my first approach for
> detecting member iterator traits, and 'empty_iterator_traits' is just an
> empty type. This definition works for both iterators that have member traits
> and iterators that are pointers; and it can be specialized for other
> iterators just as easily as the existing 'iterator_traits'.
>
> Now, 'is_iterator' can be defined in terms of Boost iterator traits using
> the second approach described above. Since 'iterator_traits<T>' can always
> be instantiated, SFINAE will take care of the rest, and we won't be bothered
> with unwanted compile errors.
>
> What are your thoughts on this approach?

Believe me, I've been over and over this one. There's no solution in
the current language. Another one is is_assignable.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk