Boost logo

Boost :

From: Bjorn.Karlsson_at_[hidden]
Date: 2004-02-23 04:44:17


> From: Daniel Frey [mailto:daniel.frey_at_[hidden]]
>
> // A strange way to retrieve my_container.begin():
> boost::prior( my_container.end(), my_container.size() );
>
> Is that legal? The second template parameter of boost::prior
> is deduced
> to an unsigned(!) type, which IMHO means that -n is
> undefined, right? Do
> we need to fix this?

It's both legal and well defined, but perhaps not very intuitive...
For unary minus, the negative of an unsigned is computed as 2^n-v (where n
is the number of bits in the type yielded by performing integral promotion
on the operand and v is the value of the operand [5.3.1/7]). The resulting
type is the promoted operand; this means that unsigned char and unsigned
short will typically work as expected with boost::prior (those types can be
promoted to int on most [all?] platforms), whereas unsigned int and unsigned
long will always return a positive value (because here, the resulting type
of integral promotion is the type of the operand, and the result of the
unary - operator is therefore 2^n-v).

So, the effect of this is that the example above is valid, but the resulting
iterator is past-the-end, typically way too far to ever be seen again...and
the name 'prior' thus becomes misleading for certain types.
 
> or shall we document that it's illegal/undefined to call
> boost::prior()
> with an unsigned second parameter?

I think Dave's suggestion of using reverse_iterator would be cool; that also
adds a good reason for using boost::prior rather than std::advance for
decrementing.
Something like this should work:

  template <class T, class Distance>
  inline T prior(T x, Distance n)
  {
    return next(std::reverse_iterator<T>(x),n).base();
  }

(Daniel, good work spotting this issue!)

Bjorn Karlsson


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