RFC on range design for D2
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Wed Sep 10 12:30:04 PDT 2008
Sergey Gromov wrote:
> Andrei Alexandrescu <SeeWebsiteForEmail at erdani.org> wrote:
>> Sergey Gromov wrote:
>>> Bill Baxter <wbaxter at gmail.com> wrote:
>>>> Here's one from DinkumWare's <algorithm>:
>>>>
>>>> template<class _BidIt1,
>>>> class _BidIt2,
>>>> class _BidIt3> inline
>>>> _BidIt3 _Merge_backward(_BidIt1 _First1, _BidIt1 _Last1,
>>>> _BidIt2 _First2, _BidIt2 _Last2, _BidIt3 _Dest, _Range_checked_iterator_tag)
>>>> { // merge backwards to _Dest, using operator<
>>>> for (; ; )
>>>> if (_First1 == _Last1)
>>>> return (_STDEXT unchecked_copy_backward(_First2, _Last2, _Dest));
>>>> else if (_First2 == _Last2)
>>>> return (_STDEXT unchecked_copy_backward(_First1, _Last1, _Dest));
>>>> else if (_DEBUG_LT(*--_Last2, *--_Last1))
>>>> *--_Dest = *_Last1, ++_Last2;
>>>> else
>>>> *--_Dest = *_Last2, ++_Last1;
>>>> }
>>>>
>>>>
>>>> You can probably work around it some way, but basically it's using the
>>>> ability to ++ and -- on the same end as a sort of "peek next".
>>> They're using the ability to ++ and -- to avoid post-decrement at any
>>> cost. Otherwise it'd be just
>>>
>>>> else if (_DEBUG_LT(*_Last2, *_Last1))
>>>> *--_Dest = *_Last1--;
>>>> else
>>>> *--_Dest = *_Last2--;
>>> Now the same algorithm in ranges:
>>>
>>>> Merge_backward(R1, R2, R3)(R1 s1, R2 s2, R3 dst)
>>>> {
>>>> for (;;)
>>>> {
>>>> if (s1.isEmpty())
>>>> dst[] = s2[];
>>>> else if (s2.isEmpty())
>>>> dst[] = s1[];
>>>> else if (s1.last < s2.last)
>>>> {
>>>> dst.last = s1.last;
>>>> s1.shrink();
>>>> }
>>>> else
>>>> {
>>>> dst.last = s2.last;
>>>> s2.shrink();
>>>> }
>>>> dst.shrink();
>>>> }
>>>> }
>>> If there were shrink-on-read and (eureka!) shrink-on-write operations,
>>> it would be even shorter:
>>>
>>>> else if (s1.last < s2.last)
>>>> dst.putBack(s1.getBack());
>>>> else
>>>> dst.putBack(s2.getBack());
>>> where both getBack() and putBack() shrink the range from the end side.
>> Got to say I'm pretty much in awe :o). But (without thinking much about
>> it) I think the assignments dst[] = s1[] and dst[] = s2[] should be
>> replaced with calls to copy(retro(sx), retro(dst)). No?
>
> They originally use backward copying because they don't know where the
> destination range starts, long live buffer overrun. In case of ranges
> the destination range is well defined and there are no overlaps---that
> is, I believe this algorithm doesn't support using the same buffer as
> source and destination. So slice copying should be OK.
One up for ranges then. Whew. I was due for it :o).
Andrei
More information about the Digitalmars-d-announce
mailing list