Boost logo

Boost :

Subject: Re: [boost] [range] [general] making member functions SFINAE-friendly
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2013-02-18 13:30:15


On Monday 18 February 2013 15:05:11 Jonathan Wakely wrote:
> On 18 February 2013 14:33, Andrey Semashev wrote:
> >
> > Yes, I'm aware of type traits. It's one thing to do tests/transforms
> > on types and another to test for methods presence and behavior. It's
> > doable but it is much more fragile and dangerous, as you have already
> > discovered with iterator_range.
>
> It's only fragile because iterator_range defines a member which can't be
> used.

No, it broke with iterator_range. It can break with other types with different
signatures and/or semantics of size().

> >> Apparently you've missed that std::list::size() is required to be O(1) in
> >> C++11.>
> > Hmm, you're right, I've missed it.
>
> Please think about what it takes for the committee to make such a
> breaking change to C++03, and whether that says the "don't define
> size() if it can't be done in constant time" principle is considered
> important or not.

Not sure what you mean.

> > vector::size() doesn't provide any benefits compared to std::distance.
>
> The fact it exists tells you it is constant time.

How so? This is true for vector as it is required by the standard but is it
true for other types? And why it should be true for iterator_range in
particular?

> If I wrote a container that could not implement empty() in O(1) then I
> would not define empty().

Great. So we only implement operations if they are possible to be implemented
in O(1) now?

> >> boost::iterator_range has size() but it results in a compile-time
> >> error. This is the worst of all combinations. It would be better to
> >> not define it at all, since users can always use std::distance on its
> >> iterators, which will be optimal for RA iterators anyway.
> >
> > Again, it's a matter of convenience. Compare:
> > r.size();
> >
> > and
> >
> > std::distance(r.begin(), r.end());
> >
> > Of course, the convenience is ruined in generic code if you have to
> > dispatch between the two variants depending on the iterator type. My
> > point is to always use the first one and be happy.
>
> Except for std::forward_list. So much for that rule.

Too bad for those trying to write a generic optimized size() implementation,
yes. But I was referring to iterator_range, specifically. It will support
size() in all cases.


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