Boost logo

Boost :

From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2006-04-16 18:14:10


On Apr 16, 2006, at 5:56 PM, David Abrahams wrote:

> Howard Hinnant <howard.hinnant_at_[hidden]> writes:
>
>> Actually in this particular case, all we need is a more smartly
>> designed std::iterator_traits class:
>>
>> Spec:
>> ---
>> template <class Iterator>
>> struct iterator_traits
>> {
>> };
>>
>> However if Iterator has the nested types: difference_type,
>> value_type, pointer, reference and iterator_category, and if
>> Iterator::iterator_category (if it exists) is implicitly convertible
>> to either std::input_iterator_tag, or std::output_iterator_tag, then
>> the struct iterator_traits is instead:
>>
>> template <class Iterator>
>> struct iterator_traits
>> {
>> typedef typename Iterator::difference_type difference_type;
>> typedef typename Iterator::value_type value_type;
>> typedef typename Iterator::pointer pointer;
>> typedef typename Iterator::reference reference;
>> typedef typename Iterator::iterator_category iterator_category;
>> };
>>
>> Plus the pointer specializations...
>> Plus any user-defined specializations...
>> ---
>>
>> Such an iterator_traits is easy to implement today with has_member_*
>> and is_convertible. And now you can say iterator_traits<any type at
>> all>. The instantiation always compiles and may or may not have the
>> nested typedefs.
>>
>> Then you can make an is_input_iterator trait:
>>
>> A type T is an input iterator if iterator_traits<T> has a member
>> called iterator_category that is convertible to
>> std::input_iterator_tag.
>
> ...which will fail even for some types that are legit members of std::
> in C++98, like
>
> std::iterator<std::input_iterator_tag, int>
>
> (false positive), not to mention types that inherit privately from
> types like the one above, or just have those names as private members
> (compile-time error).
>
> I don't mean to rain on this parade every time you bring up the idea,
> Howard; it's a nice hack. I just don't want anyone to be confused
> about that: it's a nice hack that works most of the time... and
> sometimes breaks.

Sure, but now we're in the area of intentionally breaking the
system. Concepts will not be invulnerable to deceptive coding
either. There's no structural difference between a single pass
iterator and a multi pass iterator for Concepts to check. Unless I'm
really missing something, you have to depend upon some kind of
declarative statement: "I'm a single pass iterator!" Concepts
should make it much easier to build and manipulate types of types,
and do a better job of it than just checking a single tag. But I
don't see a way to eliminate the need to ultimately trust that some
tag really means what we think it means.

Put another way, the chances of
std::iterator<std::input_iterator_tag, int> being an honest (not test
case, not intentional abuse) false positive in the wild for
is_input_iterator as I described it is probably somewhere around
0.0001%. Concepts will better those odds by another factor of 100,
or maybe even 1000. But won't eliminate the possibility.

-Howard


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