
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.