220 33201 <99d55051-ad56-4386-8a0f-9d7627b63106@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: [idea for proposal] Adding std::shift to <algorithm>
Date: Thu, 13 Jul 2017 10:21:17 -0700 (PDT)
Lines: 369
Approved: news@gmane.org
Message-ID: <99d55051-ad56-4386-8a0f-9d7627b63106@isocpp.org>
References: <bd1a5d3b-ccc1-44ab-91cc-a4d7195c9dc3@isocpp.org>
 <68bbd6d3-1578-43e1-b15f-563c9d6fb27c@isocpp.org>
 <c722a201-5c9c-4ac5-a1bd-e50beb6d7860@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_611_508594222.1499966478086"
X-Trace: blaine.gmane.org 1499966486 2806 195.159.176.226 (13 Jul 2017 17:21:26 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Thu, 13 Jul 2017 17:21:26 +0000 (UTC)
Cc: dan@soundradix.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDLZJYWNDQII5WE6ZMCRUBGLWLUAY@isocpp.org Thu Jul 13 19:21:20 2017
Return-path: <std-proposals+bncBDLZJYWNDQII5WE6ZMCRUBGLWLUAY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-it0-f69.google.com ([209.85.214.69])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDLZJYWNDQII5WE6ZMCRUBGLWLUAY@isocpp.org>)
	id 1dVhnf-00005e-51
	for gclcip-std-proposals@m.gmane.org; Thu, 13 Jul 2017 19:21:15 +0200
Original-Received: by mail-it0-f69.google.com with SMTP id k192sf73547022ith.0
        for <gclcip-std-proposals@m.gmane.org>; Thu, 13 Jul 2017 10:21:20 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:list-post:list-help:list-archive:list-subscribe
         :list-unsubscribe;
        bh=cAafWt8nWFL33BkusdUSl74jQ11dCw9S5ORf48x3BYk=;
        b=vHQBQWA/a60dD01IN5vtC+rHyBGmrGkh+alRBnoU8/ifrvooUjveXHWtsE7AmyrTAH
         FULRJ+DpDmxqGht2vGMBubdNhqBLEaqayx7C4pe031R7bHgd2P0Nfag1CYN8JFUJWfod
         4vLH0wTulwchypj0yOlrpBsipNexZ/gjv7LRSBz/PVK7PUEGhLUFh5R+rFwRWLB6C6YP
         wsKEU1JWsiCb3V9dzhBV4vevOh6rydZSgPq8o1/CGzKmWKPUrgqhjdzDwkdqREZhMdIv
         Pk7/oqFCujasUNxmqAJKYIiXY9ajHNXz2kcraZEQuA4/F8zLyHHItvsmc2VEWhy93BuL
         v6uQ==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:list-post:list-help:list-archive:list-subscribe
         :list-unsubscribe;
        bh=cAafWt8nWFL33BkusdUSl74jQ11dCw9S5ORf48x3BYk=;
        b=emfnVFxOaubXcXP2Q/inwTL8+3jczORrtqyD3s+MUo1DvnG/V08g3eX3ZN1twF1Cuz
         FWdxbutxzylrLjJgXnK6zzoHThd7+cWkcTA+Ob+AreuFxWowtMLysc86HFy4cGSy8J2E
         DAfD/5JBn4eh8lB2y9ER92LAfvcvAd/6zgyinwQMX+NDTDVk4OPb7JfaGunCzCgDDrKo
         iBW9KFIlf/CG4hfk7CFc9Hk3gPKlvCRkSTfzhZZ10fwkn371Pxv+21W4snf5E4cglrZh
         xmRMj1w/Ua4wrYU2Om6Si8GeFmVLBHAfy0zrXmYbJcERYkEzh/0kZgXzxKFHJddoaFlp
         ln3w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to
         :references:subject:mime-version:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=cAafWt8nWFL33BkusdUSl74jQ11dCw9S5ORf48x3BYk=;
        b=GBdDhF82tLzQRyk7m22eiNFiYTSslq72WJgYxrld/VJ4/+tTOIOhfv6QDa3x7W8iUc
         bRb7Rowl+f2hzMGy3d0Sf4VuiddpgUur/6fTILL7E5Xk+PDp2IldCvId3ZIl4/jc+Kkv
         +ZMLE/e5QHu9wp0/5i2i9t6vMVgiXAE6/TtD9RmsVT5Yrfee+KOFQr2N57z0TKHgnOG7
         hX88OKc0fO7ZrKa5QSCoNhKwVGoSMdZDFpK0MYiuhjkqgY1N+fulTXm4CTG3VknVlMBn
         7+7pKWo14Gvp1ch+tT2hBg5GoLwNAtBgbXKbzQvQosu2X3Q2AV+3p3qbKyLXJRjbLztz
         jPRw==
X-Gm-Message-State: AIVw111XBMKq+bp6JYNXx/r3+zqHepNCCZ/OzPnvHjnvhx8QfNuJ20rt
	mrXo4ftICaBqep8o
X-Received: by 10.107.14.82 with SMTP id 79mr3264583ioo.16.1499966480207;
        Thu, 13 Jul 2017 10:21:20 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.107.197.134 with SMTP id v128ls3208956iof.48.gmail; Thu, 13
 Jul 2017 10:21:18 -0700 (PDT)
X-Received: by 10.31.170.198 with SMTP id t189mr15289vke.13.1499966478600;
        Thu, 13 Jul 2017 10:21:18 -0700 (PDT)
In-Reply-To: <c722a201-5c9c-4ac5-a1bd-e50beb6d7860@isocpp.org>
X-Original-Sender: arthur.j.odwyer@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:33201
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/33201>

------=_Part_611_508594222.1499966478086
Content-Type: multipart/alternative; 
	boundary="----=_Part_612_799264021.1499966478087"

------=_Part_612_799264021.1499966478087
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Wednesday, July 12, 2017 at 6:43:11 PM UTC-7, Nicol Bolas wrote:
>
> On Wednesday, July 12, 2017 at 7:47:05 PM UTC-4, Arthur O'Dwyer wrote:
>>
>> On Wednesday, July 12, 2017 at 2:53:19 AM UTC-7, d...@soundradix.com=20
>> wrote:
>>>
>>> Hi,
>>>
>>> Would anyone be interested in adding std::shift to <algorithm>?=20
>>>
>>> It would be similar to both:
>>> - std::rotate, but without moving the head elements back to the tail.=
=20
>>> This would allow a more efficient implementation and clearer semantics =
in=20
>>> case rotation is not needed as well as correctness in case rotation is=
=20
>>> undesired.
>>> - <algorithm>'s std::move/std::move_backward (depending on the shift=20
>>> direction).
>>>
>>> std::shift should probably accommodate both left and right shifts by on=
e=20
>>> of:
>>> - giving it either begin() and end(), or rbegin() and rend(), similar t=
o=20
>>> how std::rotate works for both left and right rotations. The advantage =
is=20
>>> compactness of the implementation.
>>> - allowing the shift count parameter to be either positive or negative.=
=20
>>> The advantage is compactness, though it might not be clear which direct=
ion=20
>>> is which - to be consistent with rotate, positive integers should shift=
 to=20
>>> the left.
>>> - having std::shift_right and std::shift_left functions. The advantage=
=20
>>> is clarity when calling the methods, although the same argument could b=
e=20
>>> made for having separate std::rotate_left and std::rotate_right instead=
 of=20
>>> std::rotate, which we don't have.
>>>
>>
>> std::rotate is actually just a rotation; it doesn't need "left" or=20
>> "right" qualification because they're 100% equivalent. Consider a classr=
oom=20
>> globe with London in front, facing you. Now "rotate" the globe until=20
>> Beijing is in front. It doesn't matter if you rotate left or rotate righ=
t;=20
>> the outcome is exactly the same either way.
>> =20
>>
>>> Here's a sample implementation of a shift to the right direction:
>>>
>>> template<class BidirIt>=20
>>> void shift_right(BidirIt first, BidirIt last, unsigned int n =3D 1)=20
>>> {=20
>>>     std::move_backward(first, last - n, last);=20
>>> }
>>>
>>> This demonstrates that while std::shift is implementable with=20
>>> std::move/std::move_backward,
>>> 1) It isn't immediately clear from the code (at least to my eyes) that=
=20
>>> this is a shift right, unless you are intimately familiar with=20
>>> std::move_backward.
>>> 2) Different calls, either to std::move or to std::move_backward, are=
=20
>>> required, depending on the shift direction.
>>>
>>
>> If you're shifting the whole container's contents, you could use either=
=20
>> of these:
>>     std::move(ctr.rbegin() + n, ctr.rend(), ctr.rbegin());
>>     std::move_backward(ctr.begin(), ctr.end() - n, ctr.end())?
>> I don't currently see the use-case for this "shift just a piece of a=20
>> container" algorithm, I mean as distinct from std::move and=20
>> std::move_backward which already exist. Do you have a use-case?
>>
>
> The use-case would be anytime you'd want to use the code you just wrote.=
=20
> When you have a range and N, and you want to do a shift N units in that=
=20
> direction.
>
> The point of having it is one of clarification and user expectations. Yes=
,=20
> you can use `move` and `move_backward` to accomplish a shift. But conside=
r=20
> the two function calls:
>
> //A
> std::shift(rng.begin(), rng.end(), N);
>
> //B
> auto rrng =3D std::make_reverse_range(rng);
> std::move(rrng.begin() + N, rrng.end(), rrng.begin());
>
> A and B both do the same thing. But it's a *lot easier* to figure out=20
> what the code is actually accomplishing from looking at A than B.
>

Do you have a use-case for either of these?
I recall your admonition cross-thread that generally in the STL we *don't*=
=20
want to operate on containers but rather on ranges (or iterator-pairs); so=
=20
if I had a range that I wanted to "shift", I would first consider whether I=
=20
could do something like

    // OLD: shift_in_place(range, n); operate_on(range.begin(),=20
range.end());
    // NEW: operate_on(range.begin() + n, range.end());

That is, instead of moving the actual data, which might be slow, I'd move=
=20
one or the other "endpoint" while leaving the data in place.
In his reply, Dan Raviv mentioned that this is exactly the kind of thing=20
that a circular buffer does, and he's right (see proposal P0059).



B gets even more obtuse confusing in a range-based world:
>
> //A
> std::shift(rng, N);
>
> //B
> auto rrng =3D std::make_reverse_range(rng);
> std::move(std::make_range(rrng.begin + N, rrng.end()), rrng.begin());
>

In a range-based world, I would write this as

    auto output =3D input | rng::drop(n);

for a "left-shift", or... okay, the "right-shift" version is messy, at=20
least in my version, because it involves concatenating ranges one of which=
=20
needs to be created out of whole cloth, with n objects, each of which is in=
=20
a "valid but unspecified" state.  (I'd bet *money* you can't give me a=20
use-case for *that* one.)

I'd still like to see a use-case for O(n) "shifting" a sequence of elements=
=20
in-place (as opposed to using one of these range-based approaches, or using=
=20
a circular buffer, or "shifting the endpoints").  I agree that sometimes=20
you do want to copy/move the second part of a sequence over the first part,=
=20
but I would always express that in terms of "I'm std::copy'ing /=20
std::move'ing data." Expressing it as a "shift" doesn't feel natural to me=
=20
in any of the (extremely rare) use-cases I've thought of. Do you have a=20
use-case?

=E2=80=93Arthur

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/99d55051-ad56-4386-8a0f-9d7627b63106%40isocpp.or=
g.

------=_Part_612_799264021.1499966478087
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, July 12, 2017 at 6:43:11 PM UTC-7, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On W=
ednesday, July 12, 2017 at 7:47:05 PM UTC-4, Arthur O&#39;Dwyer wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, July 12, =
2017 at 2:53:19 AM UTC-7, <a>d...@soundradix.com</a> wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">Hi,<div><br></div><div>Would anyon=
e be interested in adding std::shift to &lt;algorithm&gt;?=C2=A0</div><div>=
<br></div><div>It would be similar to both:</div><div>- std::rotate, but wi=
thout moving the head elements back to the tail. This would allow a more ef=
ficient implementation and clearer semantics in case rotation is not needed=
 as well as correctness in case rotation is undesired.</div><div>- &lt;algo=
rithm&gt;&#39;s std::move/std::move_backward (depending on the shift direct=
ion).</div><div><br></div><div>std::shift should probably accommodate both =
left and right shifts by one of:</div><div>- giving it either begin() and e=
nd(), or rbegin() and rend(), similar to how std::rotate works for both lef=
t and right rotations. The advantage is compactness of the implementation.<=
/div><div>- allowing the shift count parameter to be either positive or neg=
ative. The advantage is compactness, though it might not be clear which dir=
ection is which - to be consistent with rotate, positive integers should sh=
ift to the left.<br></div><div><div>- having std::shift_right and std::shif=
t_left functions. The advantage is clarity when calling the methods, althou=
gh the same argument could be made for having separate std::rotate_left and=
 std::rotate_right instead of std::rotate, which we don&#39;t have.</div></=
div></div></blockquote><div><br></div><div>std::rotate is actually just a r=
otation; it doesn&#39;t need &quot;left&quot; or &quot;right&quot; qualific=
ation because they&#39;re 100% equivalent. Consider a classroom globe with =
London in front, facing you. Now &quot;rotate&quot; the globe until Beijing=
 is in front. It doesn&#39;t matter if you rotate left or rotate right; the=
 outcome is exactly the same either way.</div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Here&#39;s a sample imple=
mentation of a shift to the right direction:<br></div><br><div style=3D"bac=
kground-color:rgb(250,250,250);border:1px solid rgb(187,187,187);word-wrap:=
break-word"><code><div><span style=3D"color:#008">template</span><span styl=
e=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#606">BidirIt</span><span s=
tyle=3D"color:#660">&gt;</span><span style=3D"color:#000"> <br></span><span=
 style=3D"color:#008">void</span><span style=3D"color:#000"> shift_right</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#606">BidirIt</=
span><span style=3D"color:#000"> first</span><span style=3D"color:#660">,</=
span><span style=3D"color:#000"> </span><span style=3D"color:#606">BidirIt<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#008">last</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">unsigned</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">int</span><span style=3D"color:#000"> n </span>=
<span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#066">1</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> <br></span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"> <br>=C2=A0 =C2=A0 std</span><span style=3D"color:#660">:=
:</span><span style=3D"color:#000">move_backward</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">first</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>last</span><span style=3D"color:#000"> </span><span style=3D"color:#660">-=
</span><span style=3D"color:#000"> n</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">last</span=
><span style=3D"color:#660">);</span><span style=3D"color:#000"> <br></span=
><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span><=
/div></code></div><div><br></div><div>This demonstrates that while std::shi=
ft is implementable with std::move/std::move_backward,</div><div>1) It isn&=
#39;t immediately clear from the code (at least to my eyes) that this is a =
shift right, unless you are intimately familiar with std::move_backward.</d=
iv><div>2) Different calls, either to std::move or to std::move_backward, a=
re required, depending on the shift direction.</div></div></blockquote><div=
><br></div><div>If you&#39;re shifting the whole container&#39;s contents, =
you could use either of these:</div><div>=C2=A0 =C2=A0 std::move(ctr.rbegin=
() + n, ctr.rend(), ctr.rbegin());</div><div>=C2=A0 =C2=A0 std::move_backwa=
rd(ctr.begin()<wbr>, ctr.end() - n, ctr.end())?</div><div>I don&#39;t curre=
ntly see the use-case for this &quot;shift just a piece of a container&quot=
; algorithm, I mean as distinct from std::move and std::move_backward which=
 already exist. Do you have a use-case?</div></div></blockquote><div><br>Th=
e use-case would be anytime you&#39;d want to use the code you just wrote. =
When you have a range and N, and you want to do a shift N units in that dir=
ection.<br><br>The point of having it is one of clarification and user expe=
ctations. Yes, you can use `move` and `move_backward` to accomplish a shift=
.. But consider the two function calls:<br><br><div style=3D"background-colo=
r:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-=
width:1px"><code><div><span style=3D"color:#800">//A</span><span style=3D"c=
olor:#000"><br>std</span><span style=3D"color:#660">::</span><span style=3D=
"color:#000">shift</span><span style=3D"color:#660">(</span><span style=3D"=
color:#000">rng</span><span style=3D"color:#660">.</span><span style=3D"col=
or:#008">begin</span><span style=3D"color:#660">(),</span><span style=3D"co=
lor:#000"> rng</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#008">end</span><span style=3D"color:#660">(),</span><span style=3D"color=
:#000"> N</span><span style=3D"color:#660">);</span><span style=3D"color:#0=
00"><br><br></span><span style=3D"color:#800">//B</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#008">auto</span><span style=3D"col=
or:#000"> rrng </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#000">make_reverse_range</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#000">rng</span><span style=3D"color:#660">);</span><span s=
tyle=3D"color:#000"><br>std</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#000">move</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">rrng</span><span style=3D"color:#660">.</span><span sty=
le=3D"color:#008">begin</span><span style=3D"color:#660">()</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">+</span><span style=3D=
"color:#000"> N</span><span style=3D"color:#660">,</span><span style=3D"col=
or:#000"> rrng</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#008">end</span><span style=3D"color:#660">(),</span><span style=3D"color=
:#000"> rrng</span><span style=3D"color:#660">.</span><span style=3D"color:=
#008">begin</span><span style=3D"color:#660">());</span></div></code></div>=
<br>A and B both do the same thing. But it&#39;s a <i>lot easier</i> to fig=
ure out what the code is actually accomplishing from looking at A than B.<b=
r></div></div></blockquote><div><br></div><div>Do you have a use-case for e=
ither of these?</div><div>I recall your admonition cross-thread that genera=
lly in the STL we *don&#39;t* want to operate on containers but rather on r=
anges (or iterator-pairs); so if I had a range that I wanted to &quot;shift=
&quot;, I would first consider whether I could do something like</div><div>=
<br></div><div>=C2=A0 =C2=A0 // OLD: shift_in_place(range, n); operate_on(r=
ange.begin(), range.end());</div><div>=C2=A0 =C2=A0 // NEW: operate_on(rang=
e.begin() + n, range.end());</div><div><br></div><div>That is, instead of m=
oving the actual data, which might be slow, I&#39;d move one or the other &=
quot;endpoint&quot; while leaving the data in place.</div><div>In his reply=
, Dan Raviv mentioned that this is exactly the kind of thing that a circula=
r buffer does, and he&#39;s right (see proposal P0059).</div><div><br></div=
><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>B gets even more obtuse confusing in a range-based w=
orld:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:r=
gb(187,187,187);border-style:solid;border-width:1px"><code><div><span style=
=3D"color:#800">//A</span><span style=3D"color:#000"><br>std</span><span st=
yle=3D"color:#660">::</span><span style=3D"color:#000">shift</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#000">rng</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> N</span><span style=3D"=
color:#660">);</span><span style=3D"color:#000"><br><br></span><span style=
=3D"color:#800">//B</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> rrng </span><span st=
yle=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><span st=
yle=3D"color:#660">::</span><span style=3D"color:#000">make_reverse_range</=
span><span style=3D"color:#660">(</span><span style=3D"color:#000">rng</spa=
n><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>std</s=
pan><span style=3D"color:#660">::</span><span style=3D"color:#000">move</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#000">make_range</=
span><span style=3D"color:#660">(</span><span style=3D"color:#000">rrng</sp=
an><span style=3D"color:#660"><wbr>.</span><span style=3D"color:#008">begin=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">+</spa=
n><span style=3D"color:#000"> N</span><span style=3D"color:#660">,</span><s=
pan style=3D"color:#000"> rrng</span><span style=3D"color:#660">.</span><sp=
an style=3D"color:#008">end</span><span style=3D"color:#660">()),</span><sp=
an style=3D"color:#000"> rrng</span><span style=3D"color:#660">.</span><spa=
n style=3D"color:#008">begin</span><span style=3D"color:#660">());</span></=
div></code></div></div></div></blockquote><div><br></div><div>In a range-ba=
sed world, I would write this as</div><div><br></div><div>=C2=A0 =C2=A0 aut=
o output =3D input | rng::drop(n);</div><div><br></div><div>for a &quot;lef=
t-shift&quot;, or... okay, the &quot;right-shift&quot; version is messy, at=
 least in my version, because it involves concatenating ranges one of which=
 needs to be created out of whole cloth, with n objects, each of which is i=
n a &quot;valid but unspecified&quot; state. =C2=A0(I&#39;d bet <i>money</i=
> you can&#39;t give me a use-case for <i>that</i> one.)</div><div><br></di=
v><div>I&#39;d still like to see a use-case for O(n) &quot;shifting&quot; a=
 sequence of elements in-place (as opposed to using one of these range-base=
d approaches, or using a circular buffer, or &quot;shifting the endpoints&q=
uot;). =C2=A0I agree that sometimes you do want to copy/move the second par=
t of a sequence over the first part, but I would always express that in ter=
ms of &quot;I&#39;m std::copy&#39;ing / std::move&#39;ing data.&quot; Expre=
ssing it as a &quot;shift&quot; doesn&#39;t feel natural to me in any of th=
e (extremely rare) use-cases I&#39;ve thought of. Do you have a use-case?</=
div><div><br></div><div>=E2=80=93Arthur</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/99d55051-ad56-4386-8a0f-9d7627b63106%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/99d55051-ad56-4386-8a0f-9d7627b63106=
%40isocpp.org</a>.<br />

------=_Part_612_799264021.1499966478087--

------=_Part_611_508594222.1499966478086--

.
