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.


Boost list run by bdawes at, gregod at, cpdaniel at, john at