Boost logo

Boost :

Subject: Re: [boost] Is Boost.Range broken?
From: David Abrahams (dave_at_[hidden])
Date: 2008-11-21 19:42:13


on Fri Nov 21 2008, "Pete Bartlett" <pete-AT-pcbartlett.com> wrote:

>>on Fri Nov 21 2008, Tomas Puverle <Tomas.Puverle-AT-morganstanley.com>
>>wrote:
>
>>> I decided to split off this part of another thread to try to get a
>>> consensus on the changes that occurred in Boost.Range with boost
>>> 1.35. The background is discussed elsewhere. What I'd like to do
>>> here is to come to an agreement with Thorsten and other developers
>>> on the following issues:
>>>
>>> 1) Is the change in the behaviour of Boost.Range in fact a defect?
>>> 2) What should be done about it?
>>>
>>> Here are the reasons why I think Boost.Range is broken:
>
>>I think you're assuming way too much about people's familiarity with
>>the problems. The things you are saying sound serious, but I
>>certainly don't know enough about the way Range used to work and the
>>nature of the change to evaluate most of what you wrote here. Please
>>lay out, specifically, how things used to work and how they work now.
>
>>Thanks,
>
> I'll let Tomas answer for himself fully. But in short:
>
> You used to be able to call member functions on default-constructed
> iterator_ranges, now you cannot. [Apologies for the hard-coded paths
> in the following code]:
>
> ---
>
> //#include "c:/boost/boost_1_34_0/boost/range/iterator_range.hpp"
> #include "c:/boost/boost_1_36_0/boost/range/iterator_range.hpp"
>
> #include <vector>
> #include <iostream>
> #include <cstddef>
>
> int main()
> {
> boost::iterator_range< std::vector<int>::const_iterator> r;
>
> bool b1 = r.empty(); //returns true in 1.34,
> //asserts in debug 1.35+, undefined behaviour in release
> std::size_t b2 = r.size(); //returns 0 in 1.34 ,
> //asserts in debug 1.35+, undefined behaviour in release
>
> std::cout << "\n\n" << b1 << b2 << "\n\n";
> }

I certainly agree that silently dropping that guarantee is a serious
mistake. However, I'm not convinced the new behavior isn't the right
design. There's a reason that default constructed iterators aren't
required to behave except under assignment and destruction. The old
design seems to have been trying to correct something that wasn't broken
in the first place, at the cost of both space and time.

If people want an iterator_range with an empty state that consumes
storage and must be checked for on nearly every access, it should
probably be a different class template. Or vice-versa. I don't
particularly care if the non-checking one is called "range<>" or
"iterator_range<>," but if I decide to make a std::vector of
[iterator_]range<std::list<int>::iterator>, I sure don't want to pay
for more than 2 int*s per element.

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

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