Boost logo

Boost :

From: Nathan Myers (ncm-yahoospam_at_[hidden])
Date: 2001-12-28 16:25:17


On Thu, 27 Dec 2001 13:53:27 -0500, "Beman Dawes" <bdawes_at_[hidden]> wrote:

> At 03:55 AM 12/27/2001, Nathan wrote:
>
> >On Wed, 26 Dec 2001 20:05:14 -0500, "Beman Dawes" <bdawes_at_[hidden]> wrote:
> >> Did you consider asserting or throwing on b < e precondition
> >> violations?
> >
> >As a precondition, it is a logical error to insert into the set elements
> >that are already present. The type std::set<> doesn't throw if you try
> >to insert the same element again.
>
> But std::set<> doesn't have a precondition that the element can't already
> be present, and has very well defined (ignore the insert) behavior if it is
> already present.
>
> I understand the reluctance to throw, but what about asserting on any of
> the preconditions where the complexity of testing the precondition is
> minimal? Sure it is just a QOI issue, but it does help users.

In practice the way you use these things is to insert a big range, and then
carve off pieces, returning them when you're finished. You know that a range
isn't included because you know what you have and where you got it.

Testing for b > e, or b >= e, is easy and cheap, but is a very unlikely
error. Checking has_all or !has_any is more likely to catch errors, but
is quite expensive.

> > Passing a range to std::set<> with the
> >iterators reversed does not result in an exception.
>
> No, but an implementation is free to assert on that, if detectable.

Do any?

> >I cannot imagine how client code could respond meaningfully to such an
> >exception.
>
> For precondition violations, asserts are often better that exceptions. But
> there has been past discussion where people pointed out cases where assert
> was desirable in debug builds, but they would like an exception in release
> mode.

Mm, they won't get that from the regular STL components.
What exception would you suggest? I am inclined to std::logic_error.
I have included some code to do the cheaper but less useful checks.

> >> What is the rationale for the insert precondition !has_any(b, e),
> >> and the erase precondition has_all(b, e)? (I'm just curious and
> >> not suggesting that looser preconditions would be better.)
> >
> >The preconditions radically simplify the logic of the insert and erase
> >members. They correspond, logically, to the requirement the same memory
> >not be passed to free() twice. More general functions that don't impose
> >such preconditions must contain a loop. They would be easy to add (along
>
> >with general set union, intersection, and complement-intersection), and I
> >expect that will happen eventually, but they would not be a substitute
> >for the more basic operations.
>
> Understood. You might want to add the above to Rationale or FAQ docs.

I will.

> >> The portion of the license which reads "Permission is granted for
> >> any use free of charge provided..." can be read two ways:
> >> ...
> >
> >I have edited the license to eliminate any ambiguity:
> >
> >// Copyright 2001 by Nathan C. Myers <ncm-nospam_at_[hidden]>.
> >// Permission is granted free of charge for any use provided that (1)
> >// this copyright notice is retained unchanged in its entirety, and
> >// (2) the author is indemnified, held harmless, and released from all
> >// responsibility for any consequences of such use.
> >
> >As I understand it this is the minimal license that allows unrestricted
> >use without exposing me to liability.
>
> Thanks for clarifying the wording.
>
> When first looking at extent_set yesterday, I thought I'd once had a need
> for something similar, but couldn't remember the details. It has now come
> back to me, but the half-open ranges would be a problem.
>
> The problem was a QA audit program for a map database to determine if there
> was overlap in house number ranges for various records representing
> segments of a street.
>
> Thus Bound would be a class named HouseNumber. About 99% of the streets in
> the US have unsigned numeric house numbers. But the other 1% have
> different numbering schemes, with very approximately 200 in common
> use. Thus HouseNumber isn't an integer, but rather a complex class capable
> of dealing with the numbering schemes.
>
> HouseNumber is "assignable, copyable, and equality-comparable, and
> comparable using the Compare operation" but it doesn't have any increment()
> or successor() operations because for some addressing schemes there is no
> valid result possible from such an operation. That means there isn't any
> way to form a half-open range, at least not without changing HouseNumber.
>
> A specific example would be single-character alphabetic house numbers
> running from A to Z. What is the half-open range? Z doesn't have a
> successor.
>
> One solution would be to modify the HouseNumber class to add a successor,
> with a special off-the-end value. That's uncomfortable; why should a type
> which meets the requirements still need modification? There are also some
> schemes with discontinuous (although orderable) schemes; they would be an
> additional headache.
>
> I guess the question this raises is whether or not a half-open range is the
> best way to specify ranges for arbitrary types? It's really natural for
> iterators, but seems unnatural at least for the HouseNumber application.
>
> Are there killer arguments in favor of half-open ranges for extent_set?

It bothered me too that the submitted version cannot represent membership of
MAXINT. I have an implementation of extent_set using closed ranges, but it
requires both successor and predecessor functions (n + 1 and n - 1), which
had seemed to me to limit extent_set<>'s application more than the half-open
ranges. (Either would work fine for my purposes.) Of course, instead of
literally "n + 1", it says "this->succ(n)", invoking an instantiation of
a template argument. That makes the interface a little more complicated.

I have posted the closed-range implementation in the files section, under
the names "extent_set-0.2.tgz" and "extent_set-0_2.zip". See
  http://groups.yahoo.com/group/boost/files/extent_set/

It includes tests to ensure that the predecessor and successor functions
never try to generate a value that exceeds the range of the argument type.

Please let me know if you like it better.

Nathan Myers
ncm at cantrip dot org


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