
From: Daniel Frey [mailto:daniel.frey@aixigo.de]
// 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