Topic: Convert generic algorithm into generator
Author: =?UTF-8?B?0JTQuNC80LjRgtGA0LjRmCDQnNC40ZjQvtGB0LrQuA==?= <dim.mj.p@gmail.com>
Date: Wed, 3 Jan 2018 20:15:42 +0100
Raw View
--001a114a7bfaae7d2b0561e40a80
Content-Type: text/plain; charset="UTF-8"
With the addition of coroutines and generators we should also allow to
easily convert generic algorithm (that outputs into itrator/range) to
generator. The main motivation is to chain multiple algorithms without
having intermediate storage.
For example:
template< class InputIt, class OutputIt, class T >
OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
const T& value );
template< class InputIt, class OutputIt>
OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
int main()
{
vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
vector<int> tmp; // GOAL, eliminate this temporary
remove_copy(begin(v), end(v), back_inserter(tmp), 5);
vector<int> out;
unique_copy(begin(tmp), end(tmp), back_inserter(out));
}
Up to C++17, the only way to achieve the goal is to create an *seprate
iterator, e.g. class RemoveIterator* that accepts a pair of iterators, and
then put that as input into *unique_copy. *Writing custom iterators is not
the most pleasant thing because iterators are kind of simulation of
generators.
Can we achieve something like this:
int main()
{
vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
vector<int> out;
unique_copy(begin(gen), end(gen), back_inserter(out));
}
--
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 email 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/CAORbL%2BO283FfcEF%2B769MwTcMYqq%2BNhBCRKqFC3_Rze-FHuK6vw%40mail.gmail.com.
--001a114a7bfaae7d2b0561e40a80
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">With the addition of coroutines and generators we should a=
lso allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px" class=3D"gmail-prettyprint"><code class=3D"gmail-prett=
yprint"><div class=3D"gmail-subprettyprint"><div><span class=3D"gmail-mw-ge=
shi gmail-cpp gmail-source-cpp"><span class=3D"gmail-kw1"><span style=3D"co=
lor:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">template</span><span s=
tyle=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify"><</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </spa=
n><span style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">cla=
ss</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify=
"> </span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-styled-by-pre=
ttify">InputIt</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-st=
yled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-s=
tyled-by-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmai=
l-styled-by-prettify">class</span><span style=3D"color:rgb(0,0,0)" class=3D=
"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(102,0,102)" cla=
ss=3D"gmail-styled-by-prettify">OutputIt</span><span style=3D"color:rgb(102=
,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rg=
b(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:r=
gb(0,0,136)" class=3D"gmail-styled-by-prettify">class</span><span style=3D"=
color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> T </span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">></span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br></span=
><span style=3D"color:rgb(102,0,102)" class=3D"gmail-styled-by-prettify">Ou=
tputIt</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-pret=
tify"> remove_copy</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-styled-by-prettify">(</span><span style=3D"color:rgb(102,0,102)" class=3D=
"gmail-styled-by-prettify">InputIt</span><span style=3D"color:rgb(0,0,0)" c=
lass=3D"gmail-styled-by-prettify"> first</span><span style=3D"color:rgb(102=
,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rg=
b(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:r=
gb(102,0,102)" class=3D"gmail-styled-by-prettify">InputIt</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span styl=
e=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">last</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </spa=
n><span style=3D"color:rgb(102,0,102)" class=3D"gmail-styled-by-prettify">O=
utputIt</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-pre=
ttify"> d_first</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-s=
tyled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-=
styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:rgb(0,0,136)" class=
=3D"gmail-styled-by-prettify">const</span><span style=3D"color:rgb(0,0,0)" =
class=3D"gmail-styled-by-prettify"> T</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-styled-by-prettify">&</span><span style=3D"color:r=
gb(0,0,0)" class=3D"gmail-styled-by-prettify"> value </span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">);</span><span sty=
le=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br><br><br></sp=
an><span style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">te=
mplate</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-=
prettify"><</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled=
-by-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-sty=
led-by-prettify">class</span><span style=3D"color:rgb(0,0,0)" class=3D"gmai=
l-styled-by-prettify"> </span><span style=3D"color:rgb(102,0,102)" class=3D=
"gmail-styled-by-prettify">InputIt</span><span style=3D"color:rgb(102,102,0=
)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rgb(0,0,=
0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(0,0=
,136)" class=3D"gmail-styled-by-prettify">class</span><span style=3D"color:=
rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color=
:rgb(102,0,102)" class=3D"gmail-styled-by-prettify">OutputIt</span><span st=
yle=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">></span>=
<span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br></s=
pan><span style=3D"color:rgb(102,0,102)" class=3D"gmail-styled-by-prettify"=
>OutputIt</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-p=
rettify"> unique_copy</span><span style=3D"color:rgb(102,102,0)" class=3D"g=
mail-styled-by-prettify">(</span><span style=3D"color:rgb(102,0,102)" class=
=3D"gmail-styled-by-prettify">InputIt</span><span style=3D"color:rgb(0,0,0)=
" class=3D"gmail-styled-by-prettify"> first</span><span style=3D"color:rgb(=
102,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color=
:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"colo=
r:rgb(102,0,102)" class=3D"gmail-styled-by-prettify">InputIt</span><span st=
yle=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span s=
tyle=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">last</span><=
span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</s=
pan><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </=
span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-styled-by-prettify=
">OutputIt</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-=
prettify"> d_first</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-styled-by-prettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gm=
ail-styled-by-prettify"><br><br><br></span><span style=3D"color:rgb(0,0,136=
)" class=3D"gmail-styled-by-prettify">int</span><span style=3D"color:rgb(0,=
0,0)" class=3D"gmail-styled-by-prettify"> main</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-styled-by-prettify">()</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br></span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">{</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br>=C2=A0 =
=C2=A0 vector</span><span style=3D"color:rgb(0,136,0)" class=3D"gmail-style=
d-by-prettify"><int></span><span style=3D"color:rgb(0,0,0)" class=3D"=
gmail-styled-by-prettify"> v</span><span style=3D"color:rgb(102,102,0)" cla=
ss=3D"gmail-styled-by-prettify">{</span><span style=3D"color:rgb(0,102,102)=
" class=3D"gmail-styled-by-prettify">1</span><span style=3D"color:rgb(102,1=
02,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rgb(=
0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb=
(0,102,102)" class=3D"gmail-styled-by-prettify">1</span><span style=3D"colo=
r:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D=
"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=
=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">1</span><span =
style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</span><=
span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span>=
<span style=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">2</=
span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify=
">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettif=
y"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-pr=
ettify">5</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-=
by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled=
-by-prettify"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-s=
tyled-by-prettify">5</span><span style=3D"color:rgb(102,102,0)" class=3D"gm=
ail-styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"g=
mail-styled-by-prettify"> </span><span style=3D"color:rgb(0,102,102)" class=
=3D"gmail-styled-by-prettify">10</span><span style=3D"color:rgb(102,102,0)"=
class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)=
" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(0,102=
,102)" class=3D"gmail-styled-by-prettify">10</span><span style=3D"color:rgb=
(102,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"colo=
r:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"col=
or:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">11</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">};</span><span=
style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br>=C2=A0 =
=C2=A0 vector</span><span style=3D"color:rgb(0,136,0)" class=3D"gmail-style=
d-by-prettify"><int></span><span style=3D"color:rgb(0,0,0)" class=3D"=
gmail-styled-by-prettify"> tmp</span><span style=3D"color:rgb(102,102,0)" c=
lass=3D"gmail-styled-by-prettify">;</span><span style=3D"color:rgb(0,0,0)" =
class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(136,0,0=
)" class=3D"gmail-styled-by-prettify">// GOAL, eliminate this temporary</sp=
an><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br>=
=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove_copy</span><span style=3D"color:rgb(=
102,102,0)" class=3D"gmail-styled-by-prettify">(</span><span style=3D"color=
:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">begin</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">(</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify">v</span><span=
style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">),</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </spa=
n><span style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">end=
</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-pretti=
fy">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prett=
ify">v</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-=
prettify">),</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-b=
y-prettify"> back_inserter</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-styled-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" clas=
s=3D"gmail-styled-by-prettify">tmp</span><span style=3D"color:rgb(102,102,0=
)" class=3D"gmail-styled-by-prettify">),</span><span style=3D"color:rgb(0,0=
,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(0,=
102,102)" class=3D"gmail-styled-by-prettify">5</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-styled-by-prettify">);</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br><br>=C2=A0 =C2=A0 v=
ector</span><span style=3D"color:rgb(0,136,0)" class=3D"gmail-styled-by-pre=
ttify"><int></span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-st=
yled-by-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail=
-styled-by-prettify">out</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-styled-by-prettify">;</span><span style=3D"color:rgb(0,0,0)" clas=
s=3D"gmail-styled-by-prettify"><br>=C2=A0 =C2=A0 unique_copy</span><span st=
yle=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">(</span><sp=
an style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">begin</s=
pan><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify"=
>(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify=
">tmp</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-p=
rettify">),</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by=
-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-styled=
-by-prettify">end</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail=
-styled-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmai=
l-styled-by-prettify">tmp</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-styled-by-prettify">),</span><span style=3D"color:rgb(0,0,0)" cla=
ss=3D"gmail-styled-by-prettify"> back_inserter</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-styled-by-prettify">(</span><span style=3D"co=
lor:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">out</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">));</span><spa=
n style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><br></span>=
<span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">}</=
span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><b=
r></span></span></span><span class=3D"gmail-mw-geshi gmail-cpp gmail-source=
-cpp"><p><span class=3D"gmail-mw-geshi gmail-cpp gmail-source-cpp"><span cl=
ass=3D"gmail-sy4"></span></span></p></span></div></div></code></div><br>Up =
to C++17, the only way to achieve the goal is to create an <b>seprate itera=
tor, e.g. class RemoveIterator</b> that accepts a pair of iterators, and th=
en put that as input into <b>unique_copy. </b>Writing custom iterators is n=
ot the most pleasant thing because iterators are kind of simulation of gene=
rators.<br><br>Can we achieve something like this:<br><br><div style=3D"bac=
kground-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:s=
olid;border-width:1px" class=3D"gmail-prettyprint"><code class=3D"gmail-pre=
ttyprint"><div class=3D"gmail-subprettyprint"><code class=3D"gmail-prettypr=
int"><span class=3D"gmail-mw-geshi gmail-cpp gmail-source-cpp"><span class=
=3D"gmail-kw1"><span style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-=
prettify">int</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-=
by-prettify"> main</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-styled-by-prettify">()</span><span style=3D"color:rgb(0,0,0)" class=3D"gm=
ail-styled-by-prettify"><br></span><span style=3D"color:rgb(102,102,0)" cla=
ss=3D"gmail-styled-by-prettify">{</span><span style=3D"color:rgb(0,0,0)" cl=
ass=3D"gmail-styled-by-prettify"><br>=C2=A0 =C2=A0 vector</span><span style=
=3D"color:rgb(0,136,0)" class=3D"gmail-styled-by-prettify"><int></spa=
n><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> v</s=
pan><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify"=
>{</span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-pret=
tify">1</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by=
-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-b=
y-prettify"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-sty=
led-by-prettify">1</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gma=
il-styled-by-prettify"> </span><span style=3D"color:rgb(0,102,102)" class=
=3D"gmail-styled-by-prettify">1</span><span style=3D"color:rgb(102,102,0)" =
class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)"=
class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(0,102,=
102)" class=3D"gmail-styled-by-prettify">2</span><span style=3D"color:rgb(1=
02,102,0)" class=3D"gmail-styled-by-prettify">,</span><span style=3D"color:=
rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color=
:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">5</span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</span><span styl=
e=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span sty=
le=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">5</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">,</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </spa=
n><span style=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by-prettify">1=
0</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prett=
ify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-pret=
tify"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-styled-by=
-prettify">10</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-sty=
led-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-st=
yled-by-prettify"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gma=
il-styled-by-prettify">11</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-styled-by-prettify">};</span><span style=3D"color:rgb(0,0,0)" cla=
ss=3D"gmail-styled-by-prettify"><br></span><span style=3D"color:rgb(0,0,0)"=
class=3D"gmail-styled-by-prettify">=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 auto ge=
n =3D remove_copy</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail=
-styled-by-prettify">(</span><span style=3D"color:rgb(0,0,136)" class=3D"gm=
ail-styled-by-prettify">begin</span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"gmail-styled-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" c=
lass=3D"gmail-styled-by-prettify">v</span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-styled-by-prettify">),</span><span style=3D"color:rgb(0,=
0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=3D"color:rgb(0=
,0,136)" class=3D"gmail-styled-by-prettify">end</span><span style=3D"color:=
rgb(102,102,0)" class=3D"gmail-styled-by-prettify">(</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-styled-by-prettify">v</span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">),</span><span sty=
le=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> yielder<int&=
gt;{}</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-p=
rettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-=
prettify"> </span><span style=3D"color:rgb(0,102,102)" class=3D"gmail-style=
d-by-prettify">5</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-=
styled-by-prettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmai=
l-styled-by-prettify"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"col=
or:rgb(0,136,0)" class=3D"gmail-styled-by-prettify"><int></span><span=
style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><spa=
n style=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">out</span=
><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">;<=
/span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"><=
br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,102,0)" cla=
ss=3D"gmail-styled-by-prettify">(</span><span style=3D"color:rgb(0,0,136)" =
class=3D"gmail-styled-by-prettify">begin</span><span style=3D"color:rgb(102=
,102,0)" class=3D"gmail-styled-by-prettify">(gen</span><span style=3D"color=
:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"></span><span style=3D"color=
:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">),</span><span style=3D=
"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"> </span><span style=
=3D"color:rgb(0,0,136)" class=3D"gmail-styled-by-prettify">end</span><span =
style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">(gen</spa=
n><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"></spa=
n><span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify">)=
,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-styled-by-prettify"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-s=
tyled-by-prettify">(</span><span style=3D"color:rgb(0,0,136)" class=3D"gmai=
l-styled-by-prettify">out</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-styled-by-prettify">));</span><span style=3D"color:rgb(0,0,0)" cl=
ass=3D"gmail-styled-by-prettify"><br></span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-styled-by-prettify">}</span><span style=3D"color:rgb(0=
,0,0)" class=3D"gmail-styled-by-prettify"><br></span></span></span></code><=
span style=3D"color:rgb(102,102,0)" class=3D"gmail-styled-by-prettify"></sp=
an></div></code></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/CAORbL%2BO283FfcEF%2B769MwTcMYqq%2BNh=
BCRKqFC3_Rze-FHuK6vw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAORbL%2BO2=
83FfcEF%2B769MwTcMYqq%2BNhBCRKqFC3_Rze-FHuK6vw%40mail.gmail.com</a>.<br />
--001a114a7bfaae7d2b0561e40a80--
.
Author: Toby Allsopp <toby@mi6.gen.nz>
Date: Wed, 3 Jan 2018 11:34:58 -0800 (PST)
Raw View
------=_Part_13_1400518835.1515008098863
Content-Type: multipart/alternative;
boundary="----=_Part_14_1384838900.1515008098864"
------=_Part_14_1384838900.1515008098864
Content-Type: text/plain; charset="UTF-8"
You can get the chaining you want using view::filter as decribed
in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
But if you want to be able to adapt existing algorithms that take an output
iterator so that they return a Range (such as a generator) then you're
going to need something that acts as an output iterator and also acts as
(or can convert to) a Range (because the algorithms generally return one
past the last iterator they wrote to.
To make it work without a temporary, the output iterator (yielder in your
example) would need to own the elements that have been written to it, which
violates one of the characteristics of iterators, i.e. that they are cheap
(O(1)) to copy. However, I guess it could be made to work. You don't need
coroutines for this, just a weird iterator type that stores a container and
either also has begin and end members or has a conversion to something that
does (such as the container it used to store the written elements).
Cheers,
Toby.
On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>
> With the addition of coroutines and generators we should also allow to
> easily convert generic algorithm (that outputs into itrator/range) to
> generator. The main motivation is to chain multiple algorithms without
> having intermediate storage.
>
> For example:
>
> template< class InputIt, class OutputIt, class T >
> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
> const T& value );
>
>
> template< class InputIt, class OutputIt>
> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>
>
> int main()
> {
> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
> vector<int> tmp; // GOAL, eliminate this temporary
>
> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>
> vector<int> out;
> unique_copy(begin(tmp), end(tmp), back_inserter(out));
> }
>
>
> Up to C++17, the only way to achieve the goal is to create an *seprate
> iterator, e.g. class RemoveIterator* that accepts a pair of iterators,
> and then put that as input into *unique_copy. *Writing custom iterators
> is not the most pleasant thing because iterators are kind of simulation of
> generators.
>
> Can we achieve something like this:
>
> int main()
> {
> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>
> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>
> vector<int> out;
> unique_copy(begin(gen), end(gen), back_inserter(out));
> }
>
--
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 email 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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org.
------=_Part_14_1384838900.1515008098864
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">You can get the chaining you want using view::filter as de=
cribed in=C2=A0http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p078=
9r1.pdf.<div><br></div><div>But if you want to be able to adapt existing al=
gorithms that take an output iterator so that they return a Range (such as =
a generator) then you're going to need something that acts as an output=
iterator and also acts as (or can convert to) a Range (because the algorit=
hms generally return one past the last iterator they wrote to.</div><div><b=
r></div><div>To make it work without a temporary, the output iterator (yiel=
der in your example) would need to own the elements that have been written =
to it, which violates one of the characteristics of iterators, i.e. that th=
ey are cheap (O(1)) to copy. However, I guess it could be made to work. You=
don't need coroutines for this, just a weird iterator type that stores=
a container and either also has begin and end members or has a conversion =
to something that does (such as the container it used to store the written =
elements).</div><div><br></div><div>Cheers,</div><div>Toby.</div><div><br>O=
n Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:<blockq=
uote 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">With the addition of=
coroutines and generators we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4=
%40isocpp.org</a>.<br />
------=_Part_14_1384838900.1515008098864--
------=_Part_13_1400518835.1515008098863--
.
Author: =?UTF-8?B?0JTQuNC80LjRgtGA0LjRmCDQnNC40ZjQvtGB0LrQuA==?= <dim.mj.p@gmail.com>
Date: Wed, 3 Jan 2018 21:31:48 +0100
Raw View
--94eb2c060c32d745c00561e51af9
Content-Type: text/plain; charset="UTF-8"
From what i see std::view is the range equivalent of *copy_if* (or
remove_copy_if with negated predicate). The range views described in the
document are not always applicable.
Consider a more real world example.
Input, a UTF-8 narrow char sequence
Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
Algorithm 2: Unicode normalization, char32 to char32 sequence
Algorithm 3: ToLower, similar
Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
These are all complex algorithms (e.g. Finite state machines that output a
character only when some valid state is reached) and none of the standard
iterating primitives like map/filter/reduce apply.
It would be a good idea to implement these algorithms once in generic form
"algo(first, last, out)" and then reuse them in strings, vectors, maybe
wrap them as generator etc.
On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <toby@mi6.gen.nz> wrote:
> You can get the chaining you want using view::filter as decribed in
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>
> But if you want to be able to adapt existing algorithms that take an
> output iterator so that they return a Range (such as a generator) then
> you're going to need something that acts as an output iterator and also
> acts as (or can convert to) a Range (because the algorithms generally
> return one past the last iterator they wrote to.
>
> To make it work without a temporary, the output iterator (yielder in your
> example) would need to own the elements that have been written to it, which
> violates one of the characteristics of iterators, i.e. that they are cheap
> (O(1)) to copy. However, I guess it could be made to work. You don't need
> coroutines for this, just a weird iterator type that stores a container and
> either also has begin and end members or has a conversion to something that
> does (such as the container it used to store the written elements).
>
> Cheers,
> Toby.
>
> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>
>> With the addition of coroutines and generators we should also allow to
>> easily convert generic algorithm (that outputs into itrator/range) to
>> generator. The main motivation is to chain multiple algorithms without
>> having intermediate storage.
>>
>> For example:
>>
>> template< class InputIt, class OutputIt, class T >
>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>> const T& value );
>>
>>
>> template< class InputIt, class OutputIt>
>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>
>>
>> int main()
>> {
>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>> vector<int> tmp; // GOAL, eliminate this temporary
>>
>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>
>> vector<int> out;
>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>> }
>>
>>
>> Up to C++17, the only way to achieve the goal is to create an *seprate
>> iterator, e.g. class RemoveIterator* that accepts a pair of iterators,
>> and then put that as input into *unique_copy. *Writing custom iterators
>> is not the most pleasant thing because iterators are kind of simulation of
>> generators.
>>
>> Can we achieve something like this:
>>
>> int main()
>> {
>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>
>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>
>> vector<int> out;
>> unique_copy(begin(gen), end(gen), back_inserter(out));
>> }
>>
> --
> 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
> email 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/e8de40c2-ee82-484f-
> 93a0-f88cf5076bf4%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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 email 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/CAORbL%2BMxHb5QxssDO406HucTnxfnb%2B3djgj_NuE58nhWzcPrCw%40mail.gmail.com.
--94eb2c060c32d745c00561e51af9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div><div><div>From what i see std::vi=
ew is the range equivalent of <b>copy_if</b> (or remove_copy_if with negate=
d predicate). The range views described in the document are not always appl=
icable.<br><br></div>Consider a more real world example.<br></div>Input, a =
UTF-8 narrow char sequence<br></div>Algorithm 1: UTF-8 decoder, outputs a c=
har32_t sequence<br></div>Algorithm 2: Unicode normalization, char32 to cha=
r32 sequence<br></div>Algorithm 3: ToLower, similar<br></div>Algorithm 4: U=
TF-32 to UTF-8, char32 to narrow char sequence<br></div><br>These are all c=
omplex algorithms (e.g. Finite state machines that output a character only =
when some valid state is reached) and none of the standard iterating primit=
ives like map/filter/reduce apply.<br><div><div><br></div><div>It would be =
a good idea to implement these algorithms once in generic form "algo(f=
irst, last, out)" and then reuse them in strings, vectors, maybe wrap =
them as generator etc.<br></div></div><div class=3D"gmail_extra"><br><div c=
lass=3D"gmail_quote">On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <span dir=
=3D"ltr"><<a href=3D"mailto:toby@mi6.gen.nz" target=3D"_blank">toby@mi6.=
gen.nz</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr">You can get the chaining you want using view::filter as decribed in=C2=
=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789=
r1.pdf" target=3D"_blank">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/=
papers/<wbr>2017/p0789r1.pdf</a>.<div><br></div><div>But if you want to be =
able to adapt existing algorithms that take an output iterator so that they=
return a Range (such as a generator) then you're going to need somethi=
ng that acts as an output iterator and also acts as (or can convert to) a R=
ange (because the algorithms generally return one past the last iterator th=
ey wrote to.</div><div><br></div><div>To make it work without a temporary, =
the output iterator (yielder in your example) would need to own the element=
s that have been written to it, which violates one of the characteristics o=
f iterators, i.e. that they are cheap (O(1)) to copy. However, I guess it c=
ould be made to work. You don't need coroutines for this, just a weird =
iterator type that stores a container and either also has begin and end mem=
bers or has a conversion to something that does (such as the container it u=
sed to store the written elements).</div><div><br></div><div>Cheers,</div><=
div>Toby.</div><div><div class=3D"h5"><div><br>On Thursday, 4 January 2018 =
08:15:45 UTC+13, Dimitrij Mijoski 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">With the addition of coroutines and generators we sh=
ould also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span class=3D"HOEnZb"><font color=3D"=
#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de=
40c2-ee82-484f-<wbr>93a0-f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/CAORbL%2BMxHb5QxssDO406HucTnxfnb%2B3d=
jgj_NuE58nhWzcPrCw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAORbL%2BMxHb=
5QxssDO406HucTnxfnb%2B3djgj_NuE58nhWzcPrCw%40mail.gmail.com</a>.<br />
--94eb2c060c32d745c00561e51af9--
.
Author: Toby Allsopp <toby@mi6.gen.nz>
Date: Wed, 3 Jan 2018 13:03:28 -0800 (PST)
Raw View
------=_Part_488_695080542.1515013408176
Content-Type: multipart/alternative;
boundary="----=_Part_489_2023025505.1515013408177"
------=_Part_489_2023025505.1515013408177
Content-Type: text/plain; charset="UTF-8"
Sure, if you have more complicated algorithms you will need to implement
them yourself.
I interpret your question as being about what is the best way to implement
the algorithms so that they can be used either with output iterators OR
chained together.
I think the best way to do this is to make them lazy range adaptors, i.e.
accept a range and return a View that computes the results on demand.
Coroutines would certainly be useful for implementing the algorithms in
that case.
If you want to write the results to an output iterator you can simply use
copy(view, output).
For example, the signatures might be:
template <typename Utf8Range>
generator<char32_t> decode_utf8(Utf8Range&& utf8bytes);
template <typename Char32Range>
generator<char32_t> unicode_normalize(Char32Range&& chars);
template <typename Char32Range>
generator<char32_t> unicode_tolower(Char32Range&& chars);
template <typename Char32Range>
generator<char> encode_utf8(Char32Range&& chars);
Then you could compose them like so:
template <typename Utf8Range>
generator<char> utf8_tolower(Utf8Range&& utf8bytes) {
return
encode_utf8(
unicode_tolower(
unicode_normalize(
decode_utf8(
std::forward<Utf8Range>(utf8bytes)))));
}
And then, if you want an output iterator version:
template <typename Utf8Range, typename Out>
Out utf_tolower(Utf8Range&& utf8bytes, Out out) {
return std::copy(utf8_tolower(std::forward<Utf8Range>(utf8bytes), out);
}
So, my point, I think, is that I think it's better to implement algorithms
like this first as range adaptors and then put an output iterator interface
on top rather than doing it the other way around.
On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski wrote:
>
> From what i see std::view is the range equivalent of *copy_if* (or
> remove_copy_if with negated predicate). The range views described in the
> document are not always applicable.
>
> Consider a more real world example.
> Input, a UTF-8 narrow char sequence
> Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
> Algorithm 2: Unicode normalization, char32 to char32 sequence
> Algorithm 3: ToLower, similar
> Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
>
> These are all complex algorithms (e.g. Finite state machines that output a
> character only when some valid state is reached) and none of the standard
> iterating primitives like map/filter/reduce apply.
>
> It would be a good idea to implement these algorithms once in generic form
> "algo(first, last, out)" and then reuse them in strings, vectors, maybe
> wrap them as generator etc.
>
> On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <to...@mi6.gen.nz
> <javascript:>> wrote:
>
>> You can get the chaining you want using view::filter as decribed in
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>>
>> But if you want to be able to adapt existing algorithms that take an
>> output iterator so that they return a Range (such as a generator) then
>> you're going to need something that acts as an output iterator and also
>> acts as (or can convert to) a Range (because the algorithms generally
>> return one past the last iterator they wrote to.
>>
>> To make it work without a temporary, the output iterator (yielder in your
>> example) would need to own the elements that have been written to it, which
>> violates one of the characteristics of iterators, i.e. that they are cheap
>> (O(1)) to copy. However, I guess it could be made to work. You don't need
>> coroutines for this, just a weird iterator type that stores a container and
>> either also has begin and end members or has a conversion to something that
>> does (such as the container it used to store the written elements).
>>
>> Cheers,
>> Toby.
>>
>> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>>
>>> With the addition of coroutines and generators we should also allow to
>>> easily convert generic algorithm (that outputs into itrator/range) to
>>> generator. The main motivation is to chain multiple algorithms without
>>> having intermediate storage.
>>>
>>> For example:
>>>
>>> template< class InputIt, class OutputIt, class T >
>>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>>> const T& value );
>>>
>>>
>>> template< class InputIt, class OutputIt>
>>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>>
>>>
>>> int main()
>>> {
>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>> vector<int> tmp; // GOAL, eliminate this temporary
>>>
>>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>>
>>> vector<int> out;
>>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>>> }
>>>
>>>
>>> Up to C++17, the only way to achieve the goal is to create an *seprate
>>> iterator, e.g. class RemoveIterator* that accepts a pair of iterators,
>>> and then put that as input into *unique_copy. *Writing custom iterators
>>> is not the most pleasant thing because iterators are kind of simulation of
>>> generators.
>>>
>>> Can we achieve something like this:
>>>
>>> int main()
>>> {
>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>
>>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>>
>>> vector<int> out;
>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>> }
>>>
>> --
>> 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
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
>> .
>>
>
>
--
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 email 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/ed076848-98b7-4925-a97e-a6cd093f53ab%40isocpp.org.
------=_Part_489_2023025505.1515013408177
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Sure, if you have more complicated algorithms you will nee=
d to implement them yourself.<div><br></div><div>I interpret your question =
as being about what is the best way to implement the algorithms so that the=
y can be used either with output iterators OR chained together.</div><div><=
br></div><div>I think the best way to do this is to make them lazy range ad=
aptors, i.e. accept a range and return a View that computes the results on =
demand. Coroutines would certainly be useful for implementing the algorithm=
s in that case.</div><div><br></div><div>If you want to write the results t=
o an output iterator you can simply use copy(view, output).</div><div><br><=
/div><div>For example, the signatures might be:</div><div><br></div><div><d=
iv class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word=
-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Utf8Range</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>generator</span><span style=3D"color: #080;" =
class=3D"styled-by-prettify"><char32_t></span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> decode_utf8</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Utf8Range</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&&</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> utf8bytes</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">template</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
typename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Char32Range=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>generator</s=
pan><span style=3D"color: #080;" class=3D"styled-by-prettify"><char32_t&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> unicod=
e_normalize</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Char32Ra=
nge</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&&a=
mp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> chars<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">Char32Range</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>generator</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><char32_t></span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> unicode_tolower</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Char32Range</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&&</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> chars</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">template</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typ=
ename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Char32Range</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">></span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>generator</span=
><span style=3D"color: #080;" class=3D"styled-by-prettify"><char></sp=
an><font color=3D"#000000"><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> encode_utf8</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">Char32Range</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&&</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> chars</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
);</span></font></div></code></div><br>Then you could compose them like so:=
</div><div><br></div><div><div class=3D"prettyprint" style=3D"background-co=
lor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: so=
lid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"=
><div class=3D"subprettyprint"><font color=3D"#660066"><span style=3D"color=
: #008;" class=3D"styled-by-prettify">template</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">typename</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Utf8Range</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">></span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>generator</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify"><char></span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> utf8_tolower</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">Utf8Range</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> utf8bytes</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 encode_utf=
8</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
unicode_tolower</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 unicode_normalize</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 decode_utf8</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">forward</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Utf8Range</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">>(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">utf8bytes</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)))));</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">}</span></font></div></code></div><br>And then, if you want an outp=
ut iterator version:</div><div><br></div><div><div class=3D"prettyprint" st=
yle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 18=
7); border-style: solid; border-width: 1px; word-wrap: break-word;"><code c=
lass=3D"prettyprint"><div class=3D"subprettyprint"><font color=3D"#660066">=
<span style=3D"color: #008;" class=3D"styled-by-prettify">template</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;"=
class=3D"styled-by-prettify">Utf8Range</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">typename</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Out</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Out</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> utf_tolower</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Utf8Range</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&&</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> utf8bytes</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Out</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">out</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">copy</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">utf8_tolower</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">forw=
ard</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Utf8Range</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">>(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">utf8bytes</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">),</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">out</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span></font></div></code></div><br>So, my point, I thi=
nk, is that I think it's better to implement algorithms like this first=
as range adaptors and then put an output iterator interface on top rather =
than doing it the other way around.</div><div><br>On Thursday, 4 January 20=
18 09:31:51 UTC+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div><div><div><div><div><div><div>From what=
i see std::view is the range equivalent of <b>copy_if</b> (or remove_copy_=
if with negated predicate). The range views described in the document are n=
ot always applicable.<br><br></div>Consider a more real world example.<br><=
/div>Input, a UTF-8 narrow char sequence<br></div>Algorithm 1: UTF-8 decode=
r, outputs a char32_t sequence<br></div>Algorithm 2: Unicode normalization,=
char32 to char32 sequence<br></div>Algorithm 3: ToLower, similar<br></div>=
Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence<br></div><br>T=
hese are all complex algorithms (e.g. Finite state machines that output a c=
haracter only when some valid state is reached) and none of the standard it=
erating primitives like map/filter/reduce apply.<br><div><div><br></div><di=
v>It would be a good idea to implement these algorithms once in generic for=
m "algo(first, last, out)" and then reuse them in strings, vector=
s, maybe wrap them as generator etc.<br></div></div><div><br><div class=3D"=
gmail_quote">On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <span dir=3D"ltr"=
><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"2Oj=
8zP-3CwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:'=
;;return true;" onclick=3D"this.href=3D'javascript:';return true;">=
to...@mi6.gen.nz</a>></span> wrote:<br><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr">You can get the chaining you want using view::filter as decr=
ibed in=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/=
2017/p0789r1.pdf" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjt=
c1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD\x26sntz\x3=
d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';return true;" onclick=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-s=
td.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';return true=
;">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/papers/<wbr>2017/p0789r=
1.pdf</a>.<div><br></div><div>But if you want to be able to adapt existing =
algorithms that take an output iterator so that they return a Range (such a=
s a generator) then you're going to need something that acts as an outp=
ut iterator and also acts as (or can convert to) a Range (because the algor=
ithms generally return one past the last iterator they wrote to.</div><div>=
<br></div><div>To make it work without a temporary, the output iterator (yi=
elder in your example) would need to own the elements that have been writte=
n to it, which violates one of the characteristics of iterators, i.e. that =
they are cheap (O(1)) to copy. However, I guess it could be made to work. Y=
ou don't need coroutines for this, just a weird iterator type that stor=
es a container and either also has begin and end members or has a conversio=
n to something that does (such as the container it used to store the writte=
n elements).</div><div><br></div><div>Cheers,</div><div>Toby.</div><div><di=
v><div><br>On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski w=
rote:<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">With the addi=
tion of coroutines and generators we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
2Oj8zP-3CwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"2Oj8zP-3CwAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D'https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;" on=
click=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de40c2-ee82-484f-<wbr>93a0-=
f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/ed076848-98b7-4925-a97e-a6cd093f53ab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ed076848-98b7-4925-a97e-a6cd093f53ab=
%40isocpp.org</a>.<br />
------=_Part_489_2023025505.1515013408177--
------=_Part_488_695080542.1515013408176--
.
Author: Dimitrij Mijoski <dim.mj.p@gmail.com>
Date: Wed, 3 Jan 2018 16:04:53 -0800 (PST)
Raw View
------=_Part_807_2012298974.1515024294007
Content-Type: multipart/alternative;
boundary="----=_Part_808_1294555328.1515024294009"
------=_Part_808_1294555328.1515024294009
Content-Type: text/plain; charset="UTF-8"
Aha I understand your point. You propose that the core algorithm should be
written in generator form, and than a top of that we can easily get the old
generic iterator form.
My point was, there is a lot of code already written in the generic
iterator form. That form is considered the "one true and right way" still
in C++17. It would be good to be able to reuse that code, but like
generator. Maybe something like this would be more consistent:
int main()
{
vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
my_generator<int> gen;
remove_copy(begin(v), end(v), yielder(gen), 5);
vector<int> out;
unique_copy(begin(gen), end(gen), back_inserter(out));
}
The function *yielder* will return a *yield_iterator*, similar to
*back_insert_iterator*. Its *operator=* would contain a *yield statement*.
The tricky part is this. The compiler should detect that the instantiation
of the generic algorithm (*remove_copy *in the example) contains yield,
although it is somewhat hidden within the *operator=*, and it should treat
the instantiation as coroutine, and not as a function. Not sure if the
current draft on coroutines allows this, but even if it doesn't I think
small modifications are needed.
On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote:
>
> Sure, if you have more complicated algorithms you will need to implement
> them yourself.
>
> I interpret your question as being about what is the best way to implement
> the algorithms so that they can be used either with output iterators OR
> chained together.
>
> I think the best way to do this is to make them lazy range adaptors, i.e.
> accept a range and return a View that computes the results on demand.
> Coroutines would certainly be useful for implementing the algorithms in
> that case.
>
> If you want to write the results to an output iterator you can simply use
> copy(view, output).
>
> For example, the signatures might be:
>
> template <typename Utf8Range>
> generator<char32_t> decode_utf8(Utf8Range&& utf8bytes);
>
> template <typename Char32Range>
> generator<char32_t> unicode_normalize(Char32Range&& chars);
>
> template <typename Char32Range>
> generator<char32_t> unicode_tolower(Char32Range&& chars);
>
> template <typename Char32Range>
> generator<char> encode_utf8(Char32Range&& chars);
>
> Then you could compose them like so:
>
> template <typename Utf8Range>
> generator<char> utf8_tolower(Utf8Range&& utf8bytes) {
> return
> encode_utf8(
> unicode_tolower(
> unicode_normalize(
> decode_utf8(
> std::forward<Utf8Range>(utf8bytes)))));
> }
>
> And then, if you want an output iterator version:
>
> template <typename Utf8Range, typename Out>
> Out utf_tolower(Utf8Range&& utf8bytes, Out out) {
> return std::copy(utf8_tolower(std::forward<Utf8Range>(utf8bytes), out);
> }
>
> So, my point, I think, is that I think it's better to implement algorithms
> like this first as range adaptors and then put an output iterator interface
> on top rather than doing it the other way around.
>
> On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski wrote:
>>
>> From what i see std::view is the range equivalent of *copy_if* (or
>> remove_copy_if with negated predicate). The range views described in the
>> document are not always applicable.
>>
>> Consider a more real world example.
>> Input, a UTF-8 narrow char sequence
>> Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
>> Algorithm 2: Unicode normalization, char32 to char32 sequence
>> Algorithm 3: ToLower, similar
>> Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
>>
>> These are all complex algorithms (e.g. Finite state machines that output
>> a character only when some valid state is reached) and none of the standard
>> iterating primitives like map/filter/reduce apply.
>>
>> It would be a good idea to implement these algorithms once in generic
>> form "algo(first, last, out)" and then reuse them in strings, vectors,
>> maybe wrap them as generator etc.
>>
>> On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <to...@mi6.gen.nz> wrote:
>>
>>> You can get the chaining you want using view::filter as decribed in
>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>>>
>>> But if you want to be able to adapt existing algorithms that take an
>>> output iterator so that they return a Range (such as a generator) then
>>> you're going to need something that acts as an output iterator and also
>>> acts as (or can convert to) a Range (because the algorithms generally
>>> return one past the last iterator they wrote to.
>>>
>>> To make it work without a temporary, the output iterator (yielder in
>>> your example) would need to own the elements that have been written to it,
>>> which violates one of the characteristics of iterators, i.e. that they are
>>> cheap (O(1)) to copy. However, I guess it could be made to work. You don't
>>> need coroutines for this, just a weird iterator type that stores a
>>> container and either also has begin and end members or has a conversion to
>>> something that does (such as the container it used to store the written
>>> elements).
>>>
>>> Cheers,
>>> Toby.
>>>
>>> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>>>
>>>> With the addition of coroutines and generators we should also allow to
>>>> easily convert generic algorithm (that outputs into itrator/range) to
>>>> generator. The main motivation is to chain multiple algorithms without
>>>> having intermediate storage.
>>>>
>>>> For example:
>>>>
>>>> template< class InputIt, class OutputIt, class T >
>>>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>>>> const T& value );
>>>>
>>>>
>>>> template< class InputIt, class OutputIt>
>>>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>>>
>>>>
>>>> int main()
>>>> {
>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>> vector<int> tmp; // GOAL, eliminate this temporary
>>>>
>>>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>>>
>>>> vector<int> out;
>>>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>>>> }
>>>>
>>>>
>>>> Up to C++17, the only way to achieve the goal is to create an *seprate
>>>> iterator, e.g. class RemoveIterator* that accepts a pair of iterators,
>>>> and then put that as input into *unique_copy. *Writing custom
>>>> iterators is not the most pleasant thing because iterators are kind of
>>>> simulation of generators.
>>>>
>>>> Can we achieve something like this:
>>>>
>>>> int main()
>>>> {
>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>
>>>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>>>
>>>> vector<int> out;
>>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>>> }
>>>>
>>> --
>>> 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 email to std-proposal...@isocpp.org.
>>> To post to this group, send email to std-pr...@isocpp.org.
>>> To view this discussion on the web visit
>>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org
>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>>
--
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 email 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/d29af3ff-f85c-4ee3-a0b6-fcc3394be9cb%40isocpp.org.
------=_Part_808_1294555328.1515024294009
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Aha I understand your point. You propose that the core alg=
orithm should be written in generator form, and than a top of that we can e=
asily get the old generic iterator form.<br><br>My point was, there is a lo=
t of code already written in the generic iterator form. That form is consid=
ered the "one true and right way" still in C++17. It would be goo=
d to be able to reuse that code, but like generator. Maybe something like t=
his would be more consistent:<br><br><div style=3D"background-color: rgb(25=
0, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border=
-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><code><code><span><span><spa=
n style=3D"color:rgb(0,0,136)"><span style=3D"color: #008;" class=3D"styled=
-by-prettify">int</span></span><span style=3D"color:rgb(0,0,0)"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> main</span></span><span sty=
le=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by=
-prettify">()</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br></span></span><span style=3D=
"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 vector</span></span>=
<span style=3D"color:rgb(0,136,0)"><span style=3D"color: #080;" class=3D"st=
yled-by-prettify"><int></span></span><span style=3D"color:rgb(0,0,0)"=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> v</span></span>=
<span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span></span><span style=3D"color:rgb(0,102,102)"><sp=
an style=3D"color: #066;" class=3D"styled-by-prettify">1</span></span><span=
style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><span style=
=3D"color:rgb(0,102,102)"><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">1</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span></span><span style=3D"c=
olor:rgb(0,0,0)"><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color: #=
066;" class=3D"styled-by-prettify">1</span></span><span style=3D"color:rgb(=
102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span></span><span style=3D"color:rgb(0,102,102=
)"><span style=3D"color: #066;" class=3D"styled-by-prettify">2</span></span=
><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span></span><span style=3D"color:rgb(0,0,0)"><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><span st=
yle=3D"color:rgb(0,102,102)"><span style=3D"color: #066;" class=3D"styled-b=
y-prettify">5</span></span><span style=3D"color:rgb(102,102,0)"><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span></span><span style=
=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"col=
or: #066;" class=3D"styled-by-prettify">5</span></span><span style=3D"color=
:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span></span><span style=3D"color:rgb(0,10=
2,102)"><span style=3D"color: #066;" class=3D"styled-by-prettify">10</span>=
</span><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">,</span></span><span style=3D"color:rgb(0,0,0)">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><s=
pan style=3D"color:rgb(0,102,102)"><span style=3D"color: #066;" class=3D"st=
yled-by-prettify">10</span></span><span style=3D"color:rgb(102,102,0)"><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">,</span></span><span =
style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=
=3D"color: #066;" class=3D"styled-by-prettify">11</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span></span><span style=3D"c=
olor:rgb(0,0,0)"><span style=3D"color: #000;" class=3D"styled-by-prettify">=
=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 my_generator</span><span style=3D"color: #0=
80;" class=3D"styled-by-prettify"><int></span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> gen</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 remove_copy</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">begin</span></span><span style=3D=
"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:=
#000;" class=3D"styled-by-prettify">v</span></span><span style=3D"color:rg=
b(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-prettify">),<=
/span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span></span><span style=3D"color:rgb(0,0,13=
6)"><span style=3D"color: #008;" class=3D"styled-by-prettify">end</span></s=
pan><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span></span><span style=3D"color:rgb(0,0,0)"><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">v</span></span><span=
style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"style=
d-by-prettify">),</span></span><span style=3D"color:rgb(0,0,0)"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> yielder</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">gen</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span></span><span style=3D"color:rgb(102,=
102,0)"><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><=
/span><span style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span></span><span style=3D"color:rgb(0,102,102)"=
><span style=3D"color: #066;" class=3D"styled-by-prettify">5</span></span><=
span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">);</span></span><span style=3D"color:rgb(0,0,0)"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 ve=
ctor</span></span><span style=3D"color:rgb(0,136,0)"><span style=3D"color: =
#080;" class=3D"styled-by-prettify"><int></span></span><span style=3D=
"color:rgb(0,0,0)"><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"color: #=
008;" class=3D"styled-by-prettify">out</span></span><span style=3D"color:rg=
b(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 unique_copy</span></span><spa=
n style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span></span><span style=3D"color:rgb(0,0,136)"><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">begin</span></span><span s=
tyle=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">gen</span></span><span style=3D"color:rgb(0,0,0)"></span><span style=3D=
"color:rgb(102,102,0)"><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">),</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span></span><span style=3D"color:r=
gb(0,0,136)"><span style=3D"color: #008;" class=3D"styled-by-prettify">end<=
/span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">gen</span></span><span style=3D"color:rgb(0,0,0)"><=
/span><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">),</span></span><span style=3D"color:rgb(0,0,0)">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> back_inserter</s=
pan></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span></span><span style=3D"color:rgb(0,0,=
136)"><span style=3D"color: #008;" class=3D"styled-by-prettify">out</span><=
/span><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">));</span></span><span style=3D"color:rgb(0,0,0)"=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></spa=
n><span style=3D"color:rgb(102,102,0)"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></span><span style=3D"color:rgb(0,0,0)"><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></span></=
span></span></code></code></div></code></div><br>The function <b>yielder</b=
> will return a <b>yield_iterator</b>, similar to <b>back_insert_iterator</=
b>. Its <b>operator=3D</b> would contain a <b>yield statement</b>. The tric=
ky part is this. The compiler should detect that the instantiation of the g=
eneric algorithm (<b>remove_copy </b>in the example) contains yield, althou=
gh it is somewhat hidden within the <b>operator=3D</b>, and it should treat=
the instantiation as coroutine, and not as a function. Not sure if the cur=
rent draft on coroutines allows this, but even if it doesn't I think sm=
all modifications are needed.<br><br><br>On Wednesday, January 3, 2018 at 1=
0:03:28 PM UTC+1, Toby Allsopp wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr">Sure, if you have more complicated algorithms you w=
ill need to implement them yourself.<div><br></div><div>I interpret your qu=
estion as being about what is the best way to implement the algorithms so t=
hat they can be used either with output iterators OR chained together.</div=
><div><br></div><div>I think the best way to do this is to make them lazy r=
ange adaptors, i.e. accept a range and return a View that computes the resu=
lts on demand. Coroutines would certainly be useful for implementing the al=
gorithms in that case.</div><div><br></div><div>If you want to write the re=
sults to an output iterator you can simply use copy(view, output).</div><di=
v><br></div><div>For example, the signatures might be:</div><div><br></div>=
<div><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><di=
v><span style=3D"color:#008">template</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660"><</span><span style=3D"color:#008">typena=
me</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Utf8=
Range</span><span style=3D"color:#660">></span><span style=3D"color:#000=
"><br>generator</span><span style=3D"color:#080"><char32_t></span><sp=
an style=3D"color:#000"> decode_utf8</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#660">&a=
mp;&</span><span style=3D"color:#000"> utf8bytes</span><span style=3D"c=
olor:#660">);</span><span style=3D"color:#000"><br><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">typename</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Char32Range</span=
><span style=3D"color:#660">></span><span style=3D"color:#000"><br>gener=
ator</span><span style=3D"color:#080"><char32_t></span><span style=3D=
"color:#000"> unicode_normalize</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&=
<wbr>&</span><span style=3D"color:#000"> chars</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"><br><br></span><span style=3D"=
color:#008">template</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660"><</span><span style=3D"color:#008">typename</span><span =
style=3D"color:#000"> </span><span style=3D"color:#606">Char32Range</span><=
span style=3D"color:#660">></span><span style=3D"color:#000"><br>generat=
or</span><span style=3D"color:#080"><char32_t></span><span style=3D"c=
olor:#000"> unicode_tolower</span><span style=3D"color:#660">(</span><span =
style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&&=
;</span><span style=3D"color:#000"> chars</span><span style=3D"color:#660">=
);</span><span style=3D"color:#000"><br><br></span><span style=3D"color:#00=
8">template</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#606">Char32Range</span><span style=
=3D"color:#660">></span><span style=3D"color:#000"><br>generator</span><=
span style=3D"color:#080"><char></span><font color=3D"#000000"><span =
style=3D"color:#000"> encode_utf8</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&am=
p;&</span><span style=3D"color:#000"> chars</span><span style=3D"color:=
#660">);</span></font></div></code></div><br>Then you could compose them li=
ke so:</div><div><br></div><div><div style=3D"background-color:rgb(250,250,=
250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word=
-wrap:break-word"><code><div><font color=3D"#660066"><span style=3D"color:#=
008">template</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660"><</span><span style=3D"color:#008">typename</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Utf8Range</span><span style=
=3D"color:#660">></span><span style=3D"color:#000"><br>generator</span><=
span style=3D"color:#080"><char></span><span style=3D"color:#000"> ut=
f8_tolower</span><span style=3D"color:#660">(</span><span style=3D"color:#6=
06">Utf8Range</span><span style=3D"color:#660">&&</span><span style=
=3D"color:#000"> utf8bytes</span><span style=3D"color:#660">)</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">return</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 encode_utf8</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 unicod=
e_tolower</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 unicode_normalize</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 decode_utf8</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">forward</span><span style=3D"color:#660"><</span><span style=3D"col=
or:#606">Utf8Range</span><span style=3D"color:#660">>(</span><span style=
=3D"color:#000">utf8by<wbr>tes</span><span style=3D"color:#660">)))));</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span>=
</font></div></code></div><br>And then, if you want an output iterator vers=
ion:</div><div><br></div><div><div style=3D"background-color:rgb(250,250,25=
0);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-w=
rap:break-word"><code><div><font color=3D"#660066"><span style=3D"color:#00=
8">template</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#606">Utf8Range</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#606">Out</span><span style=3D"color:#660">></span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#606">Out</span><span style=3D"co=
lor:#000"> utf_tolower</span><span style=3D"color:#660">(</span><span style=
=3D"color:#606">Utf8Range</span><span style=3D"color:#660">&&</span=
><span style=3D"color:#000"> utf8bytes</span><span style=3D"color:#660">,</=
span><span style=3D"color:#000"> </span><span style=3D"color:#606">Out</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">out</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0</span><s=
pan style=3D"color:#008">return</span><span style=3D"color:#000"> std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">copy</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">utf8_tolower<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">std</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">fo<wbr>rw=
ard</span><span style=3D"color:#660"><</span><span style=3D"color:#606">=
Utf8Range</span><span style=3D"color:#660">>(</span><span style=3D"color=
:#000">utf8bytes</span><span style=3D"color:#660">),</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#008">out</span><span style=3D"colo=
r:#660">);</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">}</span></font></div></code></div><br>So, my point, I think, is that=
I think it's better to implement algorithms like this first as range a=
daptors and then put an output iterator interface on top rather than doing =
it the other way around.</div><div><br>On Thursday, 4 January 2018 09:31:51=
UTC+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div><div><div><div><div><div><div>From what i see std::view=
is the range equivalent of <b>copy_if</b> (or remove_copy_if with negated =
predicate). The range views described in the document are not always applic=
able.<br><br></div>Consider a more real world example.<br></div>Input, a UT=
F-8 narrow char sequence<br></div>Algorithm 1: UTF-8 decoder, outputs a cha=
r32_t sequence<br></div>Algorithm 2: Unicode normalization, char32 to char3=
2 sequence<br></div>Algorithm 3: ToLower, similar<br></div>Algorithm 4: UTF=
-32 to UTF-8, char32 to narrow char sequence<br></div><br>These are all com=
plex algorithms (e.g. Finite state machines that output a character only wh=
en some valid state is reached) and none of the standard iterating primitiv=
es like map/filter/reduce apply.<br><div><div><br></div><div>It would be a =
good idea to implement these algorithms once in generic form "algo(fir=
st, last, out)" and then reuse them in strings, vectors, maybe wrap th=
em as generator etc.<br></div></div><div><br><div class=3D"gmail_quote">On =
Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <span dir=3D"ltr"><<a rel=3D"n=
ofollow">to...@mi6.gen.nz</a>></span> wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr">You can get the chaining you want using view::filte=
r as decribed in=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/doc=
s/papers/2017/p0789r1.pdf" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-s=
td.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';return true=
;" onclick=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2F=
www.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\=
x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';r=
eturn true;">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/papers/<wbr>2=
017/p0789r1.pdf</a>.<div><br></div><div>But if you want to be able to adapt=
existing algorithms that take an output iterator so that they return a Ran=
ge (such as a generator) then you're going to need something that acts =
as an output iterator and also acts as (or can convert to) a Range (because=
the algorithms generally return one past the last iterator they wrote to.<=
/div><div><br></div><div>To make it work without a temporary, the output it=
erator (yielder in your example) would need to own the elements that have b=
een written to it, which violates one of the characteristics of iterators, =
i.e. that they are cheap (O(1)) to copy. However, I guess it could be made =
to work. You don't need coroutines for this, just a weird iterator type=
that stores a container and either also has begin and end members or has a=
conversion to something that does (such as the container it used to store =
the written elements).</div><div><br></div><div>Cheers,</div><div>Toby.</di=
v><div><div><div><br>On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij =
Mijoski wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Wit=
h the addition of coroutines and generators we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;" on=
click=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de40c2-ee82-484f-<wbr>93a0-=
f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/d29af3ff-f85c-4ee3-a0b6-fcc3394be9cb%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d29af3ff-f85c-4ee3-a0b6-fcc3394be9cb=
%40isocpp.org</a>.<br />
------=_Part_808_1294555328.1515024294009--
------=_Part_807_2012298974.1515024294007--
.
Author: Toby Allsopp <toby@mi6.gen.nz>
Date: Wed, 3 Jan 2018 17:14:38 -0800 (PST)
Raw View
------=_Part_870_76320630.1515028478081
Content-Type: multipart/alternative;
boundary="----=_Part_871_1302741107.1515028478083"
------=_Part_871_1302741107.1515028478083
Content-Type: text/plain; charset="UTF-8"
Oh, I think I see where you're going now. So you want to take an algorithm
that writes to an output iterator and, by passing it a special kind of
iterator, make it operate as a coroutine, suspending after yielding each
value and being resumed only when the values are requested?
That is definitely not possible with the stackless coroutines of the
Coroutines TS - a function can only be a coroutine if it directly uses one
of the co_ keywords; a function cannot suspend on behalf of another
function. I don't think a small modification will overcome this limitation
as one of the design goals of the TS (As I understand it) is that a
function needs to be aware that it can suspend, and exactly when that might
take place.
What you want is probably possible using one of the stackful coroutine
libraries, but I'm not familiar with any of them so I can't say for sure.
Cheers,
Toby.
On Thursday, 4 January 2018 13:04:54 UTC+13, Dimitrij Mijoski wrote:
>
> Aha I understand your point. You propose that the core algorithm should be
> written in generator form, and than a top of that we can easily get the old
> generic iterator form.
>
> My point was, there is a lot of code already written in the generic
> iterator form. That form is considered the "one true and right way" still
> in C++17. It would be good to be able to reuse that code, but like
> generator. Maybe something like this would be more consistent:
>
> int main()
> {
> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>
> my_generator<int> gen;
> remove_copy(begin(v), end(v), yielder(gen), 5);
>
> vector<int> out;
> unique_copy(begin(gen), end(gen), back_inserter(out));
> }
>
> The function *yielder* will return a *yield_iterator*, similar to
> *back_insert_iterator*. Its *operator=* would contain a *yield statement*.
> The tricky part is this. The compiler should detect that the instantiation
> of the generic algorithm (*remove_copy *in the example) contains yield,
> although it is somewhat hidden within the *operator=*, and it should
> treat the instantiation as coroutine, and not as a function. Not sure if
> the current draft on coroutines allows this, but even if it doesn't I think
> small modifications are needed.
>
>
> On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote:
>>
>> Sure, if you have more complicated algorithms you will need to implement
>> them yourself.
>>
>> I interpret your question as being about what is the best way to
>> implement the algorithms so that they can be used either with output
>> iterators OR chained together.
>>
>> I think the best way to do this is to make them lazy range adaptors, i.e.
>> accept a range and return a View that computes the results on demand.
>> Coroutines would certainly be useful for implementing the algorithms in
>> that case.
>>
>> If you want to write the results to an output iterator you can simply use
>> copy(view, output).
>>
>> For example, the signatures might be:
>>
>> template <typename Utf8Range>
>> generator<char32_t> decode_utf8(Utf8Range&& utf8bytes);
>>
>> template <typename Char32Range>
>> generator<char32_t> unicode_normalize(Char32Range&& chars);
>>
>> template <typename Char32Range>
>> generator<char32_t> unicode_tolower(Char32Range&& chars);
>>
>> template <typename Char32Range>
>> generator<char> encode_utf8(Char32Range&& chars);
>>
>> Then you could compose them like so:
>>
>> template <typename Utf8Range>
>> generator<char> utf8_tolower(Utf8Range&& utf8bytes) {
>> return
>> encode_utf8(
>> unicode_tolower(
>> unicode_normalize(
>> decode_utf8(
>> std::forward<Utf8Range>(utf8bytes)))));
>> }
>>
>> And then, if you want an output iterator version:
>>
>> template <typename Utf8Range, typename Out>
>> Out utf_tolower(Utf8Range&& utf8bytes, Out out) {
>> return std::copy(utf8_tolower(std::forward<Utf8Range>(utf8bytes), out);
>> }
>>
>> So, my point, I think, is that I think it's better to implement
>> algorithms like this first as range adaptors and then put an output
>> iterator interface on top rather than doing it the other way around.
>>
>> On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski wrote:
>>>
>>> From what i see std::view is the range equivalent of *copy_if* (or
>>> remove_copy_if with negated predicate). The range views described in the
>>> document are not always applicable.
>>>
>>> Consider a more real world example.
>>> Input, a UTF-8 narrow char sequence
>>> Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
>>> Algorithm 2: Unicode normalization, char32 to char32 sequence
>>> Algorithm 3: ToLower, similar
>>> Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
>>>
>>> These are all complex algorithms (e.g. Finite state machines that output
>>> a character only when some valid state is reached) and none of the standard
>>> iterating primitives like map/filter/reduce apply.
>>>
>>> It would be a good idea to implement these algorithms once in generic
>>> form "algo(first, last, out)" and then reuse them in strings, vectors,
>>> maybe wrap them as generator etc.
>>>
>>> On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <to...@mi6.gen.nz> wrote:
>>>
>>>> You can get the chaining you want using view::filter as decribed in
>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>>>>
>>>> But if you want to be able to adapt existing algorithms that take an
>>>> output iterator so that they return a Range (such as a generator) then
>>>> you're going to need something that acts as an output iterator and also
>>>> acts as (or can convert to) a Range (because the algorithms generally
>>>> return one past the last iterator they wrote to.
>>>>
>>>> To make it work without a temporary, the output iterator (yielder in
>>>> your example) would need to own the elements that have been written to it,
>>>> which violates one of the characteristics of iterators, i.e. that they are
>>>> cheap (O(1)) to copy. However, I guess it could be made to work. You don't
>>>> need coroutines for this, just a weird iterator type that stores a
>>>> container and either also has begin and end members or has a conversion to
>>>> something that does (such as the container it used to store the written
>>>> elements).
>>>>
>>>> Cheers,
>>>> Toby.
>>>>
>>>> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>>>>
>>>>> With the addition of coroutines and generators we should also allow to
>>>>> easily convert generic algorithm (that outputs into itrator/range) to
>>>>> generator. The main motivation is to chain multiple algorithms without
>>>>> having intermediate storage.
>>>>>
>>>>> For example:
>>>>>
>>>>> template< class InputIt, class OutputIt, class T >
>>>>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>>>>> const T& value );
>>>>>
>>>>>
>>>>> template< class InputIt, class OutputIt>
>>>>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>>>>
>>>>>
>>>>> int main()
>>>>> {
>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>> vector<int> tmp; // GOAL, eliminate this temporary
>>>>>
>>>>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>>>>
>>>>> vector<int> out;
>>>>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>>>>> }
>>>>>
>>>>>
>>>>> Up to C++17, the only way to achieve the goal is to create an *seprate
>>>>> iterator, e.g. class RemoveIterator* that accepts a pair of
>>>>> iterators, and then put that as input into *unique_copy. *Writing
>>>>> custom iterators is not the most pleasant thing because iterators are kind
>>>>> of simulation of generators.
>>>>>
>>>>> Can we achieve something like this:
>>>>>
>>>>> int main()
>>>>> {
>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>>
>>>>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>>>>
>>>>> vector<int> out;
>>>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>>>> }
>>>>>
>>>> --
>>>> 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 email to std-proposal...@isocpp.org.
>>>> To post to this group, send email to std-pr...@isocpp.org.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org
>>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>
>>>
--
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 email 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/6db00e86-048f-4b37-96b1-5e4a45790a2d%40isocpp.org.
------=_Part_871_1302741107.1515028478083
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Oh, I think I see where you're going now. So you want =
to take an algorithm that writes to an output iterator and, by passing it a=
special kind of iterator, make it operate as a coroutine, suspending after=
yielding each value and being resumed only when the values are requested?<=
div><br></div><div>That is definitely not possible with the stackless corou=
tines of the Coroutines TS - a function can only be a coroutine if it direc=
tly uses one of the co_ keywords; a function cannot suspend on behalf of an=
other function. I don't think a small modification will overcome this l=
imitation as one of the design goals of the TS (As I understand it) is that=
a function needs to be aware that it can suspend, and exactly when that mi=
ght take place.</div><div><br></div><div>What you want is probably possible=
using one of the stackful coroutine libraries, but I'm not familiar wi=
th any of them so I can't say for sure.</div><div><br></div><div>Cheers=
,</div><div>Toby.</div><div><br>On Thursday, 4 January 2018 13:04:54 UTC+13=
, Dimitrij Mijoski 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">Aha I understand your point. You propose that the core algorit=
hm should be written in generator form, and than a top of that we can easil=
y get the old generic iterator form.<br><br>My point was, there is a lot of=
code already written in the generic iterator form. That form is considered=
the "one true and right way" still in C++17. It would be good to=
be able to reuse that code, but like generator. Maybe something like this =
would be more consistent:<br><br><div style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><c=
ode><div><code><code><span><span><span style=3D"color:rgb(0,0,136)"><span s=
tyle=3D"color:#008">int</span></span><span style=3D"color:rgb(0,0,0)"><span=
style=3D"color:#000"> main</span></span><span style=3D"color:rgb(102,102,0=
)"><span style=3D"color:#660">()</span></span><span style=3D"color:rgb(0,0,=
0)"><span style=3D"color:#000"><br></span></span><span style=3D"color:rgb(1=
02,102,0)"><span style=3D"color:#660">{</span></span><span style=3D"color:r=
gb(0,0,0)"><span style=3D"color:#000"><br>=C2=A0 =C2=A0 vector</span></span=
><span style=3D"color:rgb(0,136,0)"><span style=3D"color:#080"><int><=
/span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> v=
</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#66=
0">{</span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color=
:#066">1</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"c=
olor:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"c=
olor:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=
=3D"color:#066">1</span></span><span style=3D"color:rgb(102,102,0)"><span s=
tyle=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span s=
tyle=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><sp=
an style=3D"color:#066">1</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"=
><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,1=
02)"><span style=3D"color:#066">2</span></span><span style=3D"color:rgb(102=
,102,0)"><span style=3D"color:#660">,</span></span><span style=3D"color:rgb=
(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb=
(0,102,102)"><span style=3D"color:#066">5</span></span><span style=3D"color=
:rgb(102,102,0)"><span style=3D"color:#660">,</span></span><span style=3D"c=
olor:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"c=
olor:rgb(0,102,102)"><span style=3D"color:#066">5</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></span><span s=
tyle=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span s=
tyle=3D"color:rgb(0,102,102)"><span style=3D"color:#066">10</span></span><s=
pan style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></spa=
n><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></spa=
n><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">10</span>=
</span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</s=
pan></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </s=
pan></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">=
11</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#=
660">};</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:=
#000"><br></span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"col=
or:#000">=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 my_generator</span><span style=3D"=
color:#080"><int></span><span style=3D"color:#000"> gen</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 re=
move_copy</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"=
color:#660">(</span></span><span style=3D"color:rgb(0,0,136)"><span style=
=3D"color:#008">begin</span></span><span style=3D"color:rgb(102,102,0)"><sp=
an style=3D"color:#660">(</span></span><span style=3D"color:rgb(0,0,0)"><sp=
an style=3D"color:#000">v</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">),</span></span><span style=3D"color:rgb(0,0,0)=
"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,0,13=
6)"><span style=3D"color:#008">end</span></span><span style=3D"color:rgb(10=
2,102,0)"><span style=3D"color:#660">(</span></span><span style=3D"color:rg=
b(0,0,0)"><span style=3D"color:#000">v</span></span><span style=3D"color:rg=
b(102,102,0)"><span style=3D"color:#660">),</span></span><span style=3D"col=
or:rgb(0,0,0)"><span style=3D"color:#000"> yielder</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">gen</span><span style=3D"color:=
#660">)</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"co=
lor:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"co=
lor:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=
=3D"color:#066">5</span></span><span style=3D"color:rgb(102,102,0)"><span s=
tyle=3D"color:#660">);</span></span><span style=3D"color:rgb(0,0,0)"><span =
style=3D"color:#000"><br><br>=C2=A0 =C2=A0 vector</span></span><span style=
=3D"color:rgb(0,136,0)"><span style=3D"color:#080"><int></span></span=
><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span=
><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#008">out</span></=
span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">;</spa=
n></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 unique_copy</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">(</span></span><span style=3D"color:rgb(0,0,136=
)"><span style=3D"color:#008">begin</span></span><span style=3D"color:rgb(1=
02,102,0)"><span style=3D"color:#660">(</span><span style=3D"color:#000">ge=
n</span></span><span style=3D"color:rgb(0,0,0)"></span><span style=3D"color=
:rgb(102,102,0)"><span style=3D"color:#660">),</span></span><span style=3D"=
color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"=
color:rgb(0,0,136)"><span style=3D"color:#008">end</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color:#660">(</span><span style=3D=
"color:#000">gen</span></span><span style=3D"color:rgb(0,0,0)"></span><span=
style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">),</span></span>=
<span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> back_inserter<=
/span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660=
">(</span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#0=
08">out</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"co=
lor:#660">));</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"=
color:#000"><br></span></span><span style=3D"color:rgb(102,102,0)"><span st=
yle=3D"color:#660">}</span></span><span style=3D"color:rgb(0,0,0)"><span st=
yle=3D"color:#000"><br></span></span></span></span></code></code></div></co=
de></div><br>The function <b>yielder</b> will return a <b>yield_iterator</b=
>, similar to <b>back_insert_iterator</b>. Its <b>operator=3D</b> would con=
tain a <b>yield statement</b>. The tricky part is this. The compiler should=
detect that the instantiation of the generic algorithm (<b>remove_copy </b=
>in the example) contains yield, although it is somewhat hidden within the =
<b>operator=3D</b>, and it should treat the instantiation as coroutine, and=
not as a function. Not sure if the current draft on coroutines allows this=
, but even if it doesn't I think small modifications are needed.<br><br=
><br>On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Sure, if you have=
more complicated algorithms you will need to implement them yourself.<div>=
<br></div><div>I interpret your question as being about what is the best wa=
y to implement the algorithms so that they can be used either with output i=
terators OR chained together.</div><div><br></div><div>I think the best way=
to do this is to make them lazy range adaptors, i.e. accept a range and re=
turn a View that computes the results on demand. Coroutines would certainly=
be useful for implementing the algorithms in that case.</div><div><br></di=
v><div>If you want to write the results to an output iterator you can simpl=
y use copy(view, output).</div><div><br></div><div>For example, the signatu=
res might be:</div><div><br></div><div><div style=3D"background-color:rgb(2=
50,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1=
px;word-wrap:break-word"><code><div><span style=3D"color:#008">template</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660"><</span=
><span style=3D"color:#008">typename</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#660">&g=
t;</span><span style=3D"color:#000"><br>generator</span><span style=3D"colo=
r:#080"><char32_t></span><span style=3D"color:#000"> decode_utf8</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#606">Utf8Range</=
span><span style=3D"color:#660">&&</span><span style=3D"color:#000"=
> utf8bytes</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br><br></span><span style=3D"color:#008">template</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Char32Range</span><span style=3D"color:#660">></span><=
span style=3D"color:#000"><br>generator</span><span style=3D"color:#080">&l=
t;char32_t></span><span style=3D"color:#000"> unicode_normalize</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range</sp=
an><span style=3D"color:#660">&<wbr>&</span><span style=3D"color:#0=
00"> chars</span><span style=3D"color:#660">);</span><span style=3D"color:#=
000"><br><br></span><span style=3D"color:#008">template</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Char32Range</span><span style=3D"color:#660">></span><=
span style=3D"color:#000"><br>generator</span><span style=3D"color:#080">&l=
t;char32_t></span><span style=3D"color:#000"> unicode_tolower</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range</span=
><span style=3D"color:#660">&&</span><span style=3D"color:#000"> ch=
ars</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><b=
r><br></span><span style=3D"color:#008">template</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color:#=
008">typename</span><span style=3D"color:#000"> </span><span style=3D"color=
:#606">Char32Range</span><span style=3D"color:#660">></span><span style=
=3D"color:#000"><br>generator</span><span style=3D"color:#080"><char>=
</span><font color=3D"#000000"><span style=3D"color:#000"> encode_utf8</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range=
</span><span style=3D"color:#660">&&</span><span style=3D"color:#00=
0"> chars</span><span style=3D"color:#660">);</span></font></div></code></d=
iv><br>Then you could compose them like so:</div><div><br></div><div><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px;word-wrap:break-word"><code><div><font col=
or=3D"#660066"><span style=3D"color:#008">template</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#606">Utf8Range</span><span style=3D"color:#660">></span><span style=
=3D"color:#000"><br>generator</span><span style=3D"color:#080"><char>=
</span><span style=3D"color:#000"> utf8_tolower</span><span style=3D"color:=
#660">(</span><span style=3D"color:#606">Utf8Range</span><span style=3D"col=
or:#660">&&</span><span style=3D"color:#000"> utf8bytes</span><span=
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span=
style=3D"color:#008">return</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 encode_utf8</span><span style=3D"color:#660">(</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 unicode_tolower</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 unicode_normalize<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 decode_utf8</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">forward</span><span style=3D"color:#=
660"><</span><span style=3D"color:#606">Utf8Range</span><span style=3D"c=
olor:#660">>(</span><span style=3D"color:#000">utf8by<wbr>tes</span><spa=
n style=3D"color:#660">)))));</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">}</span></font></div></code></div><br>And then, i=
f you want an output iterator version:</div><div><br></div><div><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px;word-wrap:break-word"><code><div><font color=
=3D"#660066"><span style=3D"color:#008">template</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color:#=
008">typename</span><span style=3D"color:#000"> </span><span style=3D"color=
:#606">Utf8Range</span><span style=3D"color:#660">,</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">typename</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Out</span><span style=3D"col=
or:#660">></span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#606">Out</span><span style=3D"color:#000"> utf_tolower</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#606">Utf8Range</span><span =
style=3D"color:#660">&&</span><span style=3D"color:#000"> utf8bytes=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#606">Out</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">out</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">copy</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">utf8_tolower</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">fo<wbr>rward</span><span style=3D"color:#660">&=
lt;</span><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#=
660">>(</span><span style=3D"color:#000">utf8bytes</span><span style=3D"=
color:#660">),</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">out</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br></span><span style=3D"color:#660">}</span></font></div></code></d=
iv><br>So, my point, I think, is that I think it's better to implement =
algorithms like this first as range adaptors and then put an output iterato=
r interface on top rather than doing it the other way around.</div><div><br=
>On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski 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"><div><div><div><div><di=
v><div><div>From what i see std::view is the range equivalent of <b>copy_if=
</b> (or remove_copy_if with negated predicate). The range views described =
in the document are not always applicable.<br><br></div>Consider a more rea=
l world example.<br></div>Input, a UTF-8 narrow char sequence<br></div>Algo=
rithm 1: UTF-8 decoder, outputs a char32_t sequence<br></div>Algorithm 2: U=
nicode normalization, char32 to char32 sequence<br></div>Algorithm 3: ToLow=
er, similar<br></div>Algorithm 4: UTF-32 to UTF-8, char32 to narrow char se=
quence<br></div><br>These are all complex algorithms (e.g. Finite state mac=
hines that output a character only when some valid state is reached) and no=
ne of the standard iterating primitives like map/filter/reduce apply.<br><d=
iv><div><br></div><div>It would be a good idea to implement these algorithm=
s once in generic form "algo(first, last, out)" and then reuse th=
em in strings, vectors, maybe wrap them as generator etc.<br></div></div><d=
iv><br><div class=3D"gmail_quote">On Wed, Jan 3, 2018 at 8:34 PM, Toby Alls=
opp <span dir=3D"ltr"><<a rel=3D"nofollow">to...@mi6.gen.nz</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">You can get th=
e chaining you want using view::filter as decribed in=C2=A0<a href=3D"http:=
//www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf" rel=3D"nofo=
llow" target=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.c=
om/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpap=
ers%2F2017%2Fp0789r1.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc=
7G2A89exP29GcPM9ww';return true;" onclick=3D"this.href=3D'http://ww=
w.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2F=
docs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
EbE2zPfzXc7G2A89exP29GcPM9ww';return true;">http://www.open-std.org/<wb=
r>jtc1/sc22/wg21/docs/papers/<wbr>2017/p0789r1.pdf</a>.<div><br></div><div>=
But if you want to be able to adapt existing algorithms that take an output=
iterator so that they return a Range (such as a generator) then you're=
going to need something that acts as an output iterator and also acts as (=
or can convert to) a Range (because the algorithms generally return one pas=
t the last iterator they wrote to.</div><div><br></div><div>To make it work=
without a temporary, the output iterator (yielder in your example) would n=
eed to own the elements that have been written to it, which violates one of=
the characteristics of iterators, i.e. that they are cheap (O(1)) to copy.=
However, I guess it could be made to work. You don't need coroutines f=
or this, just a weird iterator type that stores a container and either also=
has begin and end members or has a conversion to something that does (such=
as the container it used to store the written elements).</div><div><br></d=
iv><div>Cheers,</div><div>Toby.</div><div><div><div><br>On Thursday, 4 Janu=
ary 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr">With the addition of coroutines and generat=
ors we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;" on=
click=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de40c2-ee82-484f-<wbr>93a0-=
f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></blockquote></div></blockquote></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/6db00e86-048f-4b37-96b1-5e4a45790a2d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6db00e86-048f-4b37-96b1-5e4a45790a2d=
%40isocpp.org</a>.<br />
------=_Part_871_1302741107.1515028478083--
------=_Part_870_76320630.1515028478081--
.
Author: Dimitrij Mijoski <dim.mj.p@gmail.com>
Date: Thu, 4 Jan 2018 05:19:24 -0800 (PST)
Raw View
------=_Part_2192_974648107.1515071964431
Content-Type: multipart/alternative;
boundary="----=_Part_2193_1143431226.1515071964432"
------=_Part_2193_1143431226.1515071964432
Content-Type: text/plain; charset="UTF-8"
Yup, that is what I meant. Thanks for clarifying this stackless vs
stackfull thing.
But, I am thinking of a case where this can be achieved with stackless
coroutines. In the above example, if the *operator=* (containing the yield)
gets inlined into the generic algorithm, then the yield expression will end
up directly into the algorithm. Actually, when calling generic algorithms,
it is very much expected that all iterator operations (dereference,
increment, assignment) get inlined. With additional specification, we can
get some effect of stackfull coroutines implemented with stackless + inline
functions.
The end goal is of course, generic algorithms to be truly generic, and be
usable not just with iterators, not just with ranges, but also with lazy
ranges/generators as input and output.
On Thursday, January 4, 2018 at 2:14:38 AM UTC+1, Toby Allsopp wrote:
>
> Oh, I think I see where you're going now. So you want to take an algorithm
> that writes to an output iterator and, by passing it a special kind of
> iterator, make it operate as a coroutine, suspending after yielding each
> value and being resumed only when the values are requested?
>
> That is definitely not possible with the stackless coroutines of the
> Coroutines TS - a function can only be a coroutine if it directly uses one
> of the co_ keywords; a function cannot suspend on behalf of another
> function. I don't think a small modification will overcome this limitation
> as one of the design goals of the TS (As I understand it) is that a
> function needs to be aware that it can suspend, and exactly when that might
> take place.
>
> What you want is probably possible using one of the stackful coroutine
> libraries, but I'm not familiar with any of them so I can't say for sure.
>
> Cheers,
> Toby.
>
> On Thursday, 4 January 2018 13:04:54 UTC+13, Dimitrij Mijoski wrote:
>>
>> Aha I understand your point. You propose that the core algorithm should
>> be written in generator form, and than a top of that we can easily get the
>> old generic iterator form.
>>
>> My point was, there is a lot of code already written in the generic
>> iterator form. That form is considered the "one true and right way" still
>> in C++17. It would be good to be able to reuse that code, but like
>> generator. Maybe something like this would be more consistent:
>>
>> int main()
>> {
>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>
>> my_generator<int> gen;
>> remove_copy(begin(v), end(v), yielder(gen), 5);
>>
>> vector<int> out;
>> unique_copy(begin(gen), end(gen), back_inserter(out));
>> }
>>
>> The function *yielder* will return a *yield_iterator*, similar to
>> *back_insert_iterator*. Its *operator=* would contain a *yield statement*.
>> The tricky part is this. The compiler should detect that the instantiation
>> of the generic algorithm (*remove_copy *in the example) contains yield,
>> although it is somewhat hidden within the *operator=*, and it should
>> treat the instantiation as coroutine, and not as a function. Not sure if
>> the current draft on coroutines allows this, but even if it doesn't I think
>> small modifications are needed.
>>
>>
>> On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote:
>>>
>>> Sure, if you have more complicated algorithms you will need to implement
>>> them yourself.
>>>
>>> I interpret your question as being about what is the best way to
>>> implement the algorithms so that they can be used either with output
>>> iterators OR chained together.
>>>
>>> I think the best way to do this is to make them lazy range adaptors,
>>> i.e. accept a range and return a View that computes the results on demand.
>>> Coroutines would certainly be useful for implementing the algorithms in
>>> that case.
>>>
>>> If you want to write the results to an output iterator you can simply
>>> use copy(view, output).
>>>
>>> For example, the signatures might be:
>>>
>>> template <typename Utf8Range>
>>> generator<char32_t> decode_utf8(Utf8Range&& utf8bytes);
>>>
>>> template <typename Char32Range>
>>> generator<char32_t> unicode_normalize(Char32Range&& chars);
>>>
>>> template <typename Char32Range>
>>> generator<char32_t> unicode_tolower(Char32Range&& chars);
>>>
>>> template <typename Char32Range>
>>> generator<char> encode_utf8(Char32Range&& chars);
>>>
>>> Then you could compose them like so:
>>>
>>> template <typename Utf8Range>
>>> generator<char> utf8_tolower(Utf8Range&& utf8bytes) {
>>> return
>>> encode_utf8(
>>> unicode_tolower(
>>> unicode_normalize(
>>> decode_utf8(
>>> std::forward<Utf8Range>(utf8bytes)))));
>>> }
>>>
>>> And then, if you want an output iterator version:
>>>
>>> template <typename Utf8Range, typename Out>
>>> Out utf_tolower(Utf8Range&& utf8bytes, Out out) {
>>> return std::copy(utf8_tolower(std::forward<Utf8Range>(utf8bytes), out);
>>> }
>>>
>>> So, my point, I think, is that I think it's better to implement
>>> algorithms like this first as range adaptors and then put an output
>>> iterator interface on top rather than doing it the other way around.
>>>
>>> On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski wrote:
>>>>
>>>> From what i see std::view is the range equivalent of *copy_if* (or
>>>> remove_copy_if with negated predicate). The range views described in the
>>>> document are not always applicable.
>>>>
>>>> Consider a more real world example.
>>>> Input, a UTF-8 narrow char sequence
>>>> Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
>>>> Algorithm 2: Unicode normalization, char32 to char32 sequence
>>>> Algorithm 3: ToLower, similar
>>>> Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
>>>>
>>>> These are all complex algorithms (e.g. Finite state machines that
>>>> output a character only when some valid state is reached) and none of the
>>>> standard iterating primitives like map/filter/reduce apply.
>>>>
>>>> It would be a good idea to implement these algorithms once in generic
>>>> form "algo(first, last, out)" and then reuse them in strings, vectors,
>>>> maybe wrap them as generator etc.
>>>>
>>>> On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <to...@mi6.gen.nz> wrote:
>>>>
>>>>> You can get the chaining you want using view::filter as decribed in
>>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>>>>>
>>>>> But if you want to be able to adapt existing algorithms that take an
>>>>> output iterator so that they return a Range (such as a generator) then
>>>>> you're going to need something that acts as an output iterator and also
>>>>> acts as (or can convert to) a Range (because the algorithms generally
>>>>> return one past the last iterator they wrote to.
>>>>>
>>>>> To make it work without a temporary, the output iterator (yielder in
>>>>> your example) would need to own the elements that have been written to it,
>>>>> which violates one of the characteristics of iterators, i.e. that they are
>>>>> cheap (O(1)) to copy. However, I guess it could be made to work. You don't
>>>>> need coroutines for this, just a weird iterator type that stores a
>>>>> container and either also has begin and end members or has a conversion to
>>>>> something that does (such as the container it used to store the written
>>>>> elements).
>>>>>
>>>>> Cheers,
>>>>> Toby.
>>>>>
>>>>> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>>>>>
>>>>>> With the addition of coroutines and generators we should also allow
>>>>>> to easily convert generic algorithm (that outputs into itrator/range) to
>>>>>> generator. The main motivation is to chain multiple algorithms without
>>>>>> having intermediate storage.
>>>>>>
>>>>>> For example:
>>>>>>
>>>>>> template< class InputIt, class OutputIt, class T >
>>>>>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>>>>>> const T& value );
>>>>>>
>>>>>>
>>>>>> template< class InputIt, class OutputIt>
>>>>>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>>>>>
>>>>>>
>>>>>> int main()
>>>>>> {
>>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>>> vector<int> tmp; // GOAL, eliminate this temporary
>>>>>>
>>>>>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>>>>>
>>>>>> vector<int> out;
>>>>>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Up to C++17, the only way to achieve the goal is to create an *seprate
>>>>>> iterator, e.g. class RemoveIterator* that accepts a pair of
>>>>>> iterators, and then put that as input into *unique_copy. *Writing
>>>>>> custom iterators is not the most pleasant thing because iterators are kind
>>>>>> of simulation of generators.
>>>>>>
>>>>>> Can we achieve something like this:
>>>>>>
>>>>>> int main()
>>>>>> {
>>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>>>
>>>>>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>>>>>
>>>>>> vector<int> out;
>>>>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>>>>> }
>>>>>>
>>>>> --
>>>>> 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 email to std-proposal...@isocpp.org.
>>>>> To post to this group, send email to std-pr...@isocpp.org.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org
>>>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>
>>>>
--
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 email 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/878e0895-781c-4a9e-a956-fa5b7e687c8a%40isocpp.org.
------=_Part_2193_1143431226.1515071964432
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Yup, that is what I meant. Thanks for clarifying this stac=
kless vs stackfull thing.<br><br>But, I am thinking of a case where this ca=
n be achieved with stackless coroutines. In the above example, if the <b>op=
erator=3D</b> (containing the yield) gets inlined into the generic algorith=
m, then the yield expression will end up directly into the algorithm. Actua=
lly, when calling generic algorithms, it is very much expected that all ite=
rator operations (dereference, increment, assignment) get inlined. With add=
itional specification, we can get some effect of stackfull coroutines imple=
mented with stackless + inline functions.<br><br>The end goal is of course,=
generic algorithms to be truly generic, and be usable not just with iterat=
ors, not just with ranges, but also with lazy ranges/generators as input an=
d output.<br><br>On Thursday, January 4, 2018 at 2:14:38 AM UTC+1, Toby All=
sopp 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">Oh=
, I think I see where you're going now. So you want to take an algorith=
m that writes to an output iterator and, by passing it a special kind of it=
erator, make it operate as a coroutine, suspending after yielding each valu=
e and being resumed only when the values are requested?<div><br></div><div>=
That is definitely not possible with the stackless coroutines of the Corout=
ines TS - a function can only be a coroutine if it directly uses one of the=
co_ keywords; a function cannot suspend on behalf of another function. I d=
on't think a small modification will overcome this limitation as one of=
the design goals of the TS (As I understand it) is that a function needs t=
o be aware that it can suspend, and exactly when that might take place.</di=
v><div><br></div><div>What you want is probably possible using one of the s=
tackful coroutine libraries, but I'm not familiar with any of them so I=
can't say for sure.</div><div><br></div><div>Cheers,</div><div>Toby.</=
div><div><br>On Thursday, 4 January 2018 13:04:54 UTC+13, Dimitrij Mijoski =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Aha I under=
stand your point. You propose that the core algorithm should be written in =
generator form, and than a top of that we can easily get the old generic it=
erator form.<br><br>My point was, there is a lot of code already written in=
the generic iterator form. That form is considered the "one true and =
right way" still in C++17. It would be good to be able to reuse that c=
ode, but like generator. Maybe something like this would be more consistent=
:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(1=
87,187,187);border-style:solid;border-width:1px"><code><div><code><code><sp=
an><span><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#008">int<=
/span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> m=
ain</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:=
#660">()</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color=
:#000"><br></span></span><span style=3D"color:rgb(102,102,0)"><span style=
=3D"color:#660">{</span></span><span style=3D"color:rgb(0,0,0)"><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 vector</span></span><span style=3D"color:=
rgb(0,136,0)"><span style=3D"color:#080"><int></span></span><span sty=
le=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> v</span></span><span st=
yle=3D"color:rgb(102,102,0)"><span style=3D"color:#660">{</span></span><spa=
n style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">1</span></span>=
<span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></s=
pan><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></s=
pan><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">1</span=
></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</=
span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </=
span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066"=
>1</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#=
660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#=
000"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"col=
or:#066">2</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D=
"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D=
"color:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><span styl=
e=3D"color:#066">5</span></span><span style=3D"color:rgb(102,102,0)"><span =
style=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span =
style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><s=
pan style=3D"color:#066">5</span></span><span style=3D"color:rgb(102,102,0)=
"><span style=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)=
"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,=
102)"><span style=3D"color:#066">10</span></span><span style=3D"color:rgb(1=
02,102,0)"><span style=3D"color:#660">,</span></span><span style=3D"color:r=
gb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"color:r=
gb(0,102,102)"><span style=3D"color:#066">10</span></span><span style=3D"co=
lor:rgb(102,102,0)"><span style=3D"color:#660">,</span></span><span style=
=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=
=3D"color:rgb(0,102,102)"><span style=3D"color:#066">11</span></span><span =
style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">};</span></span><=
span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br></span></spa=
n><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000">=C2=A0 =C2=A0=
<br>=C2=A0 =C2=A0 my_generator</span><span style=3D"color:#080"><int>=
;</span><span style=3D"color:#000"> gen</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 remove_copy</span></span=
><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">(</span></=
span><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#008">begin</s=
pan></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">=
(</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000">=
v</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#6=
60">),</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#=
000"> </span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"color=
:#008">end</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D=
"color:#660">(</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D=
"color:#000">v</span></span><span style=3D"color:rgb(102,102,0)"><span styl=
e=3D"color:#660">),</span></span><span style=3D"color:rgb(0,0,0)"><span sty=
le=3D"color:#000"> yielder</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">gen</span><span style=3D"color:#660">)</span></span><sp=
an style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></span=
><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span=
><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">5</span></=
span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">);</sp=
an></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br><=
br>=C2=A0 =C2=A0 vector</span></span><span style=3D"color:rgb(0,136,0)"><sp=
an style=3D"color:#080"><int></span></span><span style=3D"color:rgb(0=
,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0=
,0,136)"><span style=3D"color:#008">out</span></span><span style=3D"color:r=
gb(102,102,0)"><span style=3D"color:#660">;</span></span><span style=3D"col=
or:rgb(0,0,0)"><span style=3D"color:#000"><br>=C2=A0 =C2=A0 unique_copy</sp=
an></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">(=
</span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#008"=
>begin</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">gen</span></span><span style=3D=
"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)"><span style=
=3D"color:#660">),</span></span><span style=3D"color:rgb(0,0,0)"><span styl=
e=3D"color:#000"> </span></span><span style=3D"color:rgb(0,0,136)"><span st=
yle=3D"color:#008">end</span></span><span style=3D"color:rgb(102,102,0)"><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">gen</span></spa=
n><span style=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,=
0)"><span style=3D"color:#660">),</span></span><span style=3D"color:rgb(0,0=
,0)"><span style=3D"color:#000"> back_inserter</span></span><span style=3D"=
color:rgb(102,102,0)"><span style=3D"color:#660">(</span></span><span style=
=3D"color:rgb(0,0,136)"><span style=3D"color:#008">out</span></span><span s=
tyle=3D"color:rgb(102,102,0)"><span style=3D"color:#660">));</span></span><=
span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br></span></spa=
n><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">}</span><=
/span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br></spa=
n></span></span></span></code></code></div></code></div><br>The function <b=
>yielder</b> will return a <b>yield_iterator</b>, similar to <b>back_insert=
_iterator</b>. Its <b>operator=3D</b> would contain a <b>yield statement</b=
>. The tricky part is this. The compiler should detect that the instantiati=
on of the generic algorithm (<b>remove_copy </b>in the example) contains yi=
eld, although it is somewhat hidden within the <b>operator=3D</b>, and it s=
hould treat the instantiation as coroutine, and not as a function. Not sure=
if the current draft on coroutines allows this, but even if it doesn't=
I think small modifications are needed.<br><br><br>On Wednesday, January 3=
, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote:<blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr">Sure, if you have more complicated algorithms=
you will need to implement them yourself.<div><br></div><div>I interpret y=
our question as being about what is the best way to implement the algorithm=
s so that they can be used either with output iterators OR chained together=
..</div><div><br></div><div>I think the best way to do this is to make them =
lazy range adaptors, i.e. accept a range and return a View that computes th=
e results on demand. Coroutines would certainly be useful for implementing =
the algorithms in that case.</div><div><br></div><div>If you want to write =
the results to an output iterator you can simply use copy(view, output).</d=
iv><div><br></div><div>For example, the signatures might be:</div><div><br>=
</div><div><div style=3D"background-color:rgb(250,250,250);border-color:rgb=
(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><co=
de><div><span style=3D"color:#008">template</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660"><</span><span style=3D"color:#008">=
typename</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">Utf8Range</span><span style=3D"color:#660">></span><span style=3D"colo=
r:#000"><br>generator</span><span style=3D"color:#080"><char32_t></sp=
an><span style=3D"color:#000"> decode_utf8</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#6=
60">&&</span><span style=3D"color:#000"> utf8bytes</span><span styl=
e=3D"color:#660">);</span><span style=3D"color:#000"><br><br></span><span s=
tyle=3D"color:#008">template</span><span style=3D"color:#000"> </span><span=
style=3D"color:#660"><</span><span style=3D"color:#008">typename</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Char32Range</=
span><span style=3D"color:#660">></span><span style=3D"color:#000"><br>g=
enerator</span><span style=3D"color:#080"><char32_t></span><span styl=
e=3D"color:#000"> unicode_normalize</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&=
amp;<wbr>&</span><span style=3D"color:#000"> chars</span><span style=3D=
"color:#660">);</span><span style=3D"color:#000"><br><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">typename</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Char32Range</span=
><span style=3D"color:#660">></span><span style=3D"color:#000"><br>gener=
ator</span><span style=3D"color:#080"><char32_t></span><span style=3D=
"color:#000"> unicode_tolower</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&&a=
mp;</span><span style=3D"color:#000"> chars</span><span style=3D"color:#660=
">);</span><span style=3D"color:#000"><br><br></span><span style=3D"color:#=
008">template</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660"><</span><span style=3D"color:#008">typename</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Char32Range</span><span styl=
e=3D"color:#660">></span><span style=3D"color:#000"><br>generator</span>=
<span style=3D"color:#080"><char></span><font color=3D"#000000"><span=
style=3D"color:#000"> encode_utf8</span><span style=3D"color:#660">(</span=
><span style=3D"color:#606">Char32Range</span><span style=3D"color:#660">&a=
mp;&</span><span style=3D"color:#000"> chars</span><span style=3D"color=
:#660">);</span></font></div></code></div><br>Then you could compose them l=
ike so:</div><div><br></div><div><div style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;wor=
d-wrap:break-word"><code><div><font color=3D"#660066"><span style=3D"color:=
#008">template</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660"><</span><span style=3D"color:#008">typename</span><span style=3D=
"color:#000"> </span><span style=3D"color:#606">Utf8Range</span><span style=
=3D"color:#660">></span><span style=3D"color:#000"><br>generator</span><=
span style=3D"color:#080"><char></span><span style=3D"color:#000"> ut=
f8_tolower</span><span style=3D"color:#660">(</span><span style=3D"color:#6=
06">Utf8Range</span><span style=3D"color:#660">&&</span><span style=
=3D"color:#000"> utf8bytes</span><span style=3D"color:#660">)</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">return</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 encode_utf8</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 unicod=
e_tolower</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 unicode_normalize</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 decode_utf8</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">forward</span><span style=3D"color:#660"><</span><span style=3D"col=
or:#606">Utf8Range</span><span style=3D"color:#660">>(</span><span style=
=3D"color:#000">utf8by<wbr>tes</span><span style=3D"color:#660">)))));</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span>=
</font></div></code></div><br>And then, if you want an output iterator vers=
ion:</div><div><br></div><div><div style=3D"background-color:rgb(250,250,25=
0);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-w=
rap:break-word"><code><div><font color=3D"#660066"><span style=3D"color:#00=
8">template</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#606">Utf8Range</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#606">Out</span><span style=3D"color:#660">></span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#606">Out</span><span style=3D"co=
lor:#000"> utf_tolower</span><span style=3D"color:#660">(</span><span style=
=3D"color:#606">Utf8Range</span><span style=3D"color:#660">&&</span=
><span style=3D"color:#000"> utf8bytes</span><span style=3D"color:#660">,</=
span><span style=3D"color:#000"> </span><span style=3D"color:#606">Out</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">out</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0</span><s=
pan style=3D"color:#008">return</span><span style=3D"color:#000"> std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">copy</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">utf8_tolower<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">std</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">fo<wbr>rw=
ard</span><span style=3D"color:#660"><</span><span style=3D"color:#606">=
Utf8Range</span><span style=3D"color:#660">>(</span><span style=3D"color=
:#000">utf8bytes</span><span style=3D"color:#660">),</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#008">out</span><span style=3D"colo=
r:#660">);</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">}</span></font></div></code></div><br>So, my point, I think, is that=
I think it's better to implement algorithms like this first as range a=
daptors and then put an output iterator interface on top rather than doing =
it the other way around.</div><div><br>On Thursday, 4 January 2018 09:31:51=
UTC+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div><div><div><div><div><div><div>From what i see std::view=
is the range equivalent of <b>copy_if</b> (or remove_copy_if with negated =
predicate). The range views described in the document are not always applic=
able.<br><br></div>Consider a more real world example.<br></div>Input, a UT=
F-8 narrow char sequence<br></div>Algorithm 1: UTF-8 decoder, outputs a cha=
r32_t sequence<br></div>Algorithm 2: Unicode normalization, char32 to char3=
2 sequence<br></div>Algorithm 3: ToLower, similar<br></div>Algorithm 4: UTF=
-32 to UTF-8, char32 to narrow char sequence<br></div><br>These are all com=
plex algorithms (e.g. Finite state machines that output a character only wh=
en some valid state is reached) and none of the standard iterating primitiv=
es like map/filter/reduce apply.<br><div><div><br></div><div>It would be a =
good idea to implement these algorithms once in generic form "algo(fir=
st, last, out)" and then reuse them in strings, vectors, maybe wrap th=
em as generator etc.<br></div></div><div><br><div class=3D"gmail_quote">On =
Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <span dir=3D"ltr"><<a rel=3D"n=
ofollow">to...@mi6.gen.nz</a>></span> wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr">You can get the chaining you want using view::filte=
r as decribed in=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/doc=
s/papers/2017/p0789r1.pdf" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-s=
td.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';return true=
;" onclick=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2F=
www.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0789r1.pdf\=
x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc7G2A89exP29GcPM9ww';r=
eturn true;">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/papers/<wbr>2=
017/p0789r1.pdf</a>.<div><br></div><div>But if you want to be able to adapt=
existing algorithms that take an output iterator so that they return a Ran=
ge (such as a generator) then you're going to need something that acts =
as an output iterator and also acts as (or can convert to) a Range (because=
the algorithms generally return one past the last iterator they wrote to.<=
/div><div><br></div><div>To make it work without a temporary, the output it=
erator (yielder in your example) would need to own the elements that have b=
een written to it, which violates one of the characteristics of iterators, =
i.e. that they are cheap (O(1)) to copy. However, I guess it could be made =
to work. You don't need coroutines for this, just a weird iterator type=
that stores a container and either also has begin and end members or has a=
conversion to something that does (such as the container it used to store =
the written elements).</div><div><br></div><div>Cheers,</div><div>Toby.</di=
v><div><div><div><br>On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij =
Mijoski wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Wit=
h the addition of coroutines and generators we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;" on=
click=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de40c2-ee82-484f-<wbr>93a0-=
f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></blockquote></div></blockquote></div></div></bloc=
kquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/878e0895-781c-4a9e-a956-fa5b7e687c8a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/878e0895-781c-4a9e-a956-fa5b7e687c8a=
%40isocpp.org</a>.<br />
------=_Part_2193_1143431226.1515071964432--
------=_Part_2192_974648107.1515071964431--
.
Author: Toby Allsopp <toby@mi6.gen.nz>
Date: Thu, 4 Jan 2018 12:36:25 -0800 (PST)
Raw View
------=_Part_3538_468820411.1515098185801
Content-Type: multipart/alternative;
boundary="----=_Part_3539_1060509906.1515098185803"
------=_Part_3539_1060509906.1515098185803
Content-Type: text/plain; charset="UTF-8"
Ah, there was a discussion a while ago about using very inline functions as
a kind of macro facility. Have a look for "operator try".
I think it's a big can of worms to allow an inlined function call to be
able to do things such as co_yield or return on behalf of the calling
function, but such a facility could be very useful. I think it would still
be necessary for the calling function to explicitly ask for or allow that
to happen in some way.
But I think it would be better as a stand-alone feature rather than as a
tweak to the Coroutines TS, although the application of turing algorithms
into coroutines could be one of the use-cases justifying such a proposal.
Cheers,
Toby.
On Friday, 5 January 2018 02:19:24 UTC+13, Dimitrij Mijoski wrote:
>
> Yup, that is what I meant. Thanks for clarifying this stackless vs
> stackfull thing.
>
> But, I am thinking of a case where this can be achieved with stackless
> coroutines. In the above example, if the *operator=* (containing the
> yield) gets inlined into the generic algorithm, then the yield expression
> will end up directly into the algorithm. Actually, when calling generic
> algorithms, it is very much expected that all iterator operations
> (dereference, increment, assignment) get inlined. With additional
> specification, we can get some effect of stackfull coroutines implemented
> with stackless + inline functions.
>
> The end goal is of course, generic algorithms to be truly generic, and be
> usable not just with iterators, not just with ranges, but also with lazy
> ranges/generators as input and output.
>
> On Thursday, January 4, 2018 at 2:14:38 AM UTC+1, Toby Allsopp wrote:
>>
>> Oh, I think I see where you're going now. So you want to take an
>> algorithm that writes to an output iterator and, by passing it a special
>> kind of iterator, make it operate as a coroutine, suspending after yielding
>> each value and being resumed only when the values are requested?
>>
>> That is definitely not possible with the stackless coroutines of the
>> Coroutines TS - a function can only be a coroutine if it directly uses one
>> of the co_ keywords; a function cannot suspend on behalf of another
>> function. I don't think a small modification will overcome this limitation
>> as one of the design goals of the TS (As I understand it) is that a
>> function needs to be aware that it can suspend, and exactly when that might
>> take place.
>>
>> What you want is probably possible using one of the stackful coroutine
>> libraries, but I'm not familiar with any of them so I can't say for sure.
>>
>> Cheers,
>> Toby.
>>
>> On Thursday, 4 January 2018 13:04:54 UTC+13, Dimitrij Mijoski wrote:
>>>
>>> Aha I understand your point. You propose that the core algorithm should
>>> be written in generator form, and than a top of that we can easily get the
>>> old generic iterator form.
>>>
>>> My point was, there is a lot of code already written in the generic
>>> iterator form. That form is considered the "one true and right way" still
>>> in C++17. It would be good to be able to reuse that code, but like
>>> generator. Maybe something like this would be more consistent:
>>>
>>> int main()
>>> {
>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>
>>> my_generator<int> gen;
>>> remove_copy(begin(v), end(v), yielder(gen), 5);
>>>
>>> vector<int> out;
>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>> }
>>>
>>> The function *yielder* will return a *yield_iterator*, similar to
>>> *back_insert_iterator*. Its *operator=* would contain a *yield
>>> statement*. The tricky part is this. The compiler should detect that
>>> the instantiation of the generic algorithm (*remove_copy *in the
>>> example) contains yield, although it is somewhat hidden within the
>>> *operator=*, and it should treat the instantiation as coroutine, and
>>> not as a function. Not sure if the current draft on coroutines allows this,
>>> but even if it doesn't I think small modifications are needed.
>>>
>>>
>>> On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote:
>>>>
>>>> Sure, if you have more complicated algorithms you will need to
>>>> implement them yourself.
>>>>
>>>> I interpret your question as being about what is the best way to
>>>> implement the algorithms so that they can be used either with output
>>>> iterators OR chained together.
>>>>
>>>> I think the best way to do this is to make them lazy range adaptors,
>>>> i.e. accept a range and return a View that computes the results on demand.
>>>> Coroutines would certainly be useful for implementing the algorithms in
>>>> that case.
>>>>
>>>> If you want to write the results to an output iterator you can simply
>>>> use copy(view, output).
>>>>
>>>> For example, the signatures might be:
>>>>
>>>> template <typename Utf8Range>
>>>> generator<char32_t> decode_utf8(Utf8Range&& utf8bytes);
>>>>
>>>> template <typename Char32Range>
>>>> generator<char32_t> unicode_normalize(Char32Range&& chars);
>>>>
>>>> template <typename Char32Range>
>>>> generator<char32_t> unicode_tolower(Char32Range&& chars);
>>>>
>>>> template <typename Char32Range>
>>>> generator<char> encode_utf8(Char32Range&& chars);
>>>>
>>>> Then you could compose them like so:
>>>>
>>>> template <typename Utf8Range>
>>>> generator<char> utf8_tolower(Utf8Range&& utf8bytes) {
>>>> return
>>>> encode_utf8(
>>>> unicode_tolower(
>>>> unicode_normalize(
>>>> decode_utf8(
>>>> std::forward<Utf8Range>(utf8bytes)))));
>>>> }
>>>>
>>>> And then, if you want an output iterator version:
>>>>
>>>> template <typename Utf8Range, typename Out>
>>>> Out utf_tolower(Utf8Range&& utf8bytes, Out out) {
>>>> return std::copy(utf8_tolower(std::forward<Utf8Range>(utf8bytes), out
>>>> );
>>>> }
>>>>
>>>> So, my point, I think, is that I think it's better to implement
>>>> algorithms like this first as range adaptors and then put an output
>>>> iterator interface on top rather than doing it the other way around.
>>>>
>>>> On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski wrote:
>>>>>
>>>>> From what i see std::view is the range equivalent of *copy_if* (or
>>>>> remove_copy_if with negated predicate). The range views described in the
>>>>> document are not always applicable.
>>>>>
>>>>> Consider a more real world example.
>>>>> Input, a UTF-8 narrow char sequence
>>>>> Algorithm 1: UTF-8 decoder, outputs a char32_t sequence
>>>>> Algorithm 2: Unicode normalization, char32 to char32 sequence
>>>>> Algorithm 3: ToLower, similar
>>>>> Algorithm 4: UTF-32 to UTF-8, char32 to narrow char sequence
>>>>>
>>>>> These are all complex algorithms (e.g. Finite state machines that
>>>>> output a character only when some valid state is reached) and none of the
>>>>> standard iterating primitives like map/filter/reduce apply.
>>>>>
>>>>> It would be a good idea to implement these algorithms once in generic
>>>>> form "algo(first, last, out)" and then reuse them in strings, vectors,
>>>>> maybe wrap them as generator etc.
>>>>>
>>>>> On Wed, Jan 3, 2018 at 8:34 PM, Toby Allsopp <to...@mi6.gen.nz> wrote:
>>>>>
>>>>>> You can get the chaining you want using view::filter as decribed in
>>>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf.
>>>>>>
>>>>>> But if you want to be able to adapt existing algorithms that take an
>>>>>> output iterator so that they return a Range (such as a generator) then
>>>>>> you're going to need something that acts as an output iterator and also
>>>>>> acts as (or can convert to) a Range (because the algorithms generally
>>>>>> return one past the last iterator they wrote to.
>>>>>>
>>>>>> To make it work without a temporary, the output iterator (yielder in
>>>>>> your example) would need to own the elements that have been written to it,
>>>>>> which violates one of the characteristics of iterators, i.e. that they are
>>>>>> cheap (O(1)) to copy. However, I guess it could be made to work. You don't
>>>>>> need coroutines for this, just a weird iterator type that stores a
>>>>>> container and either also has begin and end members or has a conversion to
>>>>>> something that does (such as the container it used to store the written
>>>>>> elements).
>>>>>>
>>>>>> Cheers,
>>>>>> Toby.
>>>>>>
>>>>>> On Thursday, 4 January 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:
>>>>>>>
>>>>>>> With the addition of coroutines and generators we should also allow
>>>>>>> to easily convert generic algorithm (that outputs into itrator/range) to
>>>>>>> generator. The main motivation is to chain multiple algorithms without
>>>>>>> having intermediate storage.
>>>>>>>
>>>>>>> For example:
>>>>>>>
>>>>>>> template< class InputIt, class OutputIt, class T >
>>>>>>> OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
>>>>>>> const T& value );
>>>>>>>
>>>>>>>
>>>>>>> template< class InputIt, class OutputIt>
>>>>>>> OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);
>>>>>>>
>>>>>>>
>>>>>>> int main()
>>>>>>> {
>>>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>>>> vector<int> tmp; // GOAL, eliminate this temporary
>>>>>>>
>>>>>>> remove_copy(begin(v), end(v), back_inserter(tmp), 5);
>>>>>>>
>>>>>>> vector<int> out;
>>>>>>> unique_copy(begin(tmp), end(tmp), back_inserter(out));
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Up to C++17, the only way to achieve the goal is to create an *seprate
>>>>>>> iterator, e.g. class RemoveIterator* that accepts a pair of
>>>>>>> iterators, and then put that as input into *unique_copy. *Writing
>>>>>>> custom iterators is not the most pleasant thing because iterators are kind
>>>>>>> of simulation of generators.
>>>>>>>
>>>>>>> Can we achieve something like this:
>>>>>>>
>>>>>>> int main()
>>>>>>> {
>>>>>>> vector<int> v{1, 1, 1, 2, 5, 5, 10, 10, 11};
>>>>>>>
>>>>>>> auto gen = remove_copy(begin(v), end(v), yielder<int>{}, 5);
>>>>>>>
>>>>>>> vector<int> out;
>>>>>>> unique_copy(begin(gen), end(gen), back_inserter(out));
>>>>>>> }
>>>>>>>
>>>>>> --
>>>>>> 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 email to std-proposal...@isocpp.org.
>>>>>> To post to this group, send email to std-pr...@isocpp.org.
>>>>>> To view this discussion on the web visit
>>>>>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org
>>>>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>>
>>>>>
--
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 email 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/14f721d0-e69f-4075-9ce0-bf4eae12b1a3%40isocpp.org.
------=_Part_3539_1060509906.1515098185803
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ah, there was a discussion a while ago about using very in=
line functions as a kind of macro facility. Have a look for "operator =
try".<div><br></div><div>I think it's a big can of worms to allow =
an inlined function call to be able to do things such as <font face=3D"cour=
ier new, monospace">co_yield </font>or <font face=3D"courier new, monospace=
">return </font>on behalf of the calling function, but such a facility coul=
d be very useful. I think it would still be necessary for the calling funct=
ion to explicitly ask for or allow that to happen in some way.</div><div><b=
r></div><div>But I think it would be better as a stand-alone feature rather=
than as a tweak to the Coroutines TS, although the application of turing a=
lgorithms into coroutines could be one of the use-cases justifying such a p=
roposal.</div><div><br></div><div>Cheers,</div><div>Toby.<br><br>On Friday,=
5 January 2018 02:19:24 UTC+13, Dimitrij Mijoski wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr">Yup, that is what I meant. Tha=
nks for clarifying this stackless vs stackfull thing.<br><br>But, I am thin=
king of a case where this can be achieved with stackless coroutines. In the=
above example, if the <b>operator=3D</b> (containing the yield) gets inlin=
ed into the generic algorithm, then the yield expression will end up direct=
ly into the algorithm. Actually, when calling generic algorithms, it is ver=
y much expected that all iterator operations (dereference, increment, assig=
nment) get inlined. With additional specification, we can get some effect o=
f stackfull coroutines implemented with stackless + inline functions.<br><b=
r>The end goal is of course, generic algorithms to be truly generic, and be=
usable not just with iterators, not just with ranges, but also with lazy r=
anges/generators as input and output.<br><br>On Thursday, January 4, 2018 a=
t 2:14:38 AM UTC+1, Toby Allsopp wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr">Oh, I think I see where you're going now. So you w=
ant to take an algorithm that writes to an output iterator and, by passing =
it a special kind of iterator, make it operate as a coroutine, suspending a=
fter yielding each value and being resumed only when the values are request=
ed?<div><br></div><div>That is definitely not possible with the stackless c=
oroutines of the Coroutines TS - a function can only be a coroutine if it d=
irectly uses one of the co_ keywords; a function cannot suspend on behalf o=
f another function. I don't think a small modification will overcome th=
is limitation as one of the design goals of the TS (As I understand it) is =
that a function needs to be aware that it can suspend, and exactly when tha=
t might take place.</div><div><br></div><div>What you want is probably poss=
ible using one of the stackful coroutine libraries, but I'm not familia=
r with any of them so I can't say for sure.</div><div><br></div><div>Ch=
eers,</div><div>Toby.</div><div><br>On Thursday, 4 January 2018 13:04:54 UT=
C+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr">Aha I understand your point. You propose that the core algorith=
m should be written in generator form, and than a top of that we can easily=
get the old generic iterator form.<br><br>My point was, there is a lot of =
code already written in the generic iterator form. That form is considered =
the "one true and right way" still in C++17. It would be good to =
be able to reuse that code, but like generator. Maybe something like this w=
ould be more consistent:<br><br><div style=3D"background-color:rgb(250,250,=
250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><co=
de><div><code><code><span><span><span style=3D"color:rgb(0,0,136)"><span st=
yle=3D"color:#008">int</span></span><span style=3D"color:rgb(0,0,0)"><span =
style=3D"color:#000"> main</span></span><span style=3D"color:rgb(102,102,0)=
"><span style=3D"color:#660">()</span></span><span style=3D"color:rgb(0,0,0=
)"><span style=3D"color:#000"><br></span></span><span style=3D"color:rgb(10=
2,102,0)"><span style=3D"color:#660">{</span></span><span style=3D"color:rg=
b(0,0,0)"><span style=3D"color:#000"><br>=C2=A0 =C2=A0 vector</span></span>=
<span style=3D"color:rgb(0,136,0)"><span style=3D"color:#080"><int></=
span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> v<=
/span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660=
">{</span></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color:=
#066">1</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"co=
lor:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"co=
lor:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=
=3D"color:#066">1</span></span><span style=3D"color:rgb(102,102,0)"><span s=
tyle=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span s=
tyle=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><sp=
an style=3D"color:#066">1</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">,</span></span><span style=3D"color:rgb(0,0,0)"=
><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,102,1=
02)"><span style=3D"color:#066">2</span></span><span style=3D"color:rgb(102=
,102,0)"><span style=3D"color:#660">,</span></span><span style=3D"color:rgb=
(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb=
(0,102,102)"><span style=3D"color:#066">5</span></span><span style=3D"color=
:rgb(102,102,0)"><span style=3D"color:#660">,</span></span><span style=3D"c=
olor:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"c=
olor:rgb(0,102,102)"><span style=3D"color:#066">5</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></span><span s=
tyle=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span s=
tyle=3D"color:rgb(0,102,102)"><span style=3D"color:#066">10</span></span><s=
pan style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</span></spa=
n><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></spa=
n><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">10</span>=
</span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">,</s=
pan></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </s=
pan></span><span style=3D"color:rgb(0,102,102)"><span style=3D"color:#066">=
11</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#=
660">};</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:=
#000"><br></span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"col=
or:#000">=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 my_generator</span><span style=3D"=
color:#080"><int></span><span style=3D"color:#000"> gen</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 re=
move_copy</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"=
color:#660">(</span></span><span style=3D"color:rgb(0,0,136)"><span style=
=3D"color:#008">begin</span></span><span style=3D"color:rgb(102,102,0)"><sp=
an style=3D"color:#660">(</span></span><span style=3D"color:rgb(0,0,0)"><sp=
an style=3D"color:#000">v</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">),</span></span><span style=3D"color:rgb(0,0,0)=
"><span style=3D"color:#000"> </span></span><span style=3D"color:rgb(0,0,13=
6)"><span style=3D"color:#008">end</span></span><span style=3D"color:rgb(10=
2,102,0)"><span style=3D"color:#660">(</span></span><span style=3D"color:rg=
b(0,0,0)"><span style=3D"color:#000">v</span></span><span style=3D"color:rg=
b(102,102,0)"><span style=3D"color:#660">),</span></span><span style=3D"col=
or:rgb(0,0,0)"><span style=3D"color:#000"> yielder</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">gen</span><span style=3D"color:=
#660">)</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"co=
lor:#660">,</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"co=
lor:#000"> </span></span><span style=3D"color:rgb(0,102,102)"><span style=
=3D"color:#066">5</span></span><span style=3D"color:rgb(102,102,0)"><span s=
tyle=3D"color:#660">);</span></span><span style=3D"color:rgb(0,0,0)"><span =
style=3D"color:#000"><br><br>=C2=A0 =C2=A0 vector</span></span><span style=
=3D"color:rgb(0,136,0)"><span style=3D"color:#080"><int></span></span=
><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span=
><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#008">out</span></=
span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">;</spa=
n></span><span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 unique_copy</span></span><span style=3D"color:rgb(102,102,0)"=
><span style=3D"color:#660">(</span></span><span style=3D"color:rgb(0,0,136=
)"><span style=3D"color:#008">begin</span></span><span style=3D"color:rgb(1=
02,102,0)"><span style=3D"color:#660">(</span><span style=3D"color:#000">ge=
n</span></span><span style=3D"color:rgb(0,0,0)"></span><span style=3D"color=
:rgb(102,102,0)"><span style=3D"color:#660">),</span></span><span style=3D"=
color:rgb(0,0,0)"><span style=3D"color:#000"> </span></span><span style=3D"=
color:rgb(0,0,136)"><span style=3D"color:#008">end</span></span><span style=
=3D"color:rgb(102,102,0)"><span style=3D"color:#660">(</span><span style=3D=
"color:#000">gen</span></span><span style=3D"color:rgb(0,0,0)"></span><span=
style=3D"color:rgb(102,102,0)"><span style=3D"color:#660">),</span></span>=
<span style=3D"color:rgb(0,0,0)"><span style=3D"color:#000"> back_inserter<=
/span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"color:#660=
">(</span></span><span style=3D"color:rgb(0,0,136)"><span style=3D"color:#0=
08">out</span></span><span style=3D"color:rgb(102,102,0)"><span style=3D"co=
lor:#660">));</span></span><span style=3D"color:rgb(0,0,0)"><span style=3D"=
color:#000"><br></span></span><span style=3D"color:rgb(102,102,0)"><span st=
yle=3D"color:#660">}</span></span><span style=3D"color:rgb(0,0,0)"><span st=
yle=3D"color:#000"><br></span></span></span></span></code></code></div></co=
de></div><br>The function <b>yielder</b> will return a <b>yield_iterator</b=
>, similar to <b>back_insert_iterator</b>. Its <b>operator=3D</b> would con=
tain a <b>yield statement</b>. The tricky part is this. The compiler should=
detect that the instantiation of the generic algorithm (<b>remove_copy </b=
>in the example) contains yield, although it is somewhat hidden within the =
<b>operator=3D</b>, and it should treat the instantiation as coroutine, and=
not as a function. Not sure if the current draft on coroutines allows this=
, but even if it doesn't I think small modifications are needed.<br><br=
><br>On Wednesday, January 3, 2018 at 10:03:28 PM UTC+1, Toby Allsopp wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Sure, if you have=
more complicated algorithms you will need to implement them yourself.<div>=
<br></div><div>I interpret your question as being about what is the best wa=
y to implement the algorithms so that they can be used either with output i=
terators OR chained together.</div><div><br></div><div>I think the best way=
to do this is to make them lazy range adaptors, i.e. accept a range and re=
turn a View that computes the results on demand. Coroutines would certainly=
be useful for implementing the algorithms in that case.</div><div><br></di=
v><div>If you want to write the results to an output iterator you can simpl=
y use copy(view, output).</div><div><br></div><div>For example, the signatu=
res might be:</div><div><br></div><div><div style=3D"background-color:rgb(2=
50,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1=
px;word-wrap:break-word"><code><div><span style=3D"color:#008">template</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660"><</span=
><span style=3D"color:#008">typename</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#660">&g=
t;</span><span style=3D"color:#000"><br>generator</span><span style=3D"colo=
r:#080"><char32_t></span><span style=3D"color:#000"> decode_utf8</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#606">Utf8Range</=
span><span style=3D"color:#660">&&</span><span style=3D"color:#000"=
> utf8bytes</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br><br></span><span style=3D"color:#008">template</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Char32Range</span><span style=3D"color:#660">></span><=
span style=3D"color:#000"><br>generator</span><span style=3D"color:#080">&l=
t;char32_t></span><span style=3D"color:#000"> unicode_normalize</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range</sp=
an><span style=3D"color:#660">&<wbr>&</span><span style=3D"color:#0=
00"> chars</span><span style=3D"color:#660">);</span><span style=3D"color:#=
000"><br><br></span><span style=3D"color:#008">template</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Char32Range</span><span style=3D"color:#660">></span><=
span style=3D"color:#000"><br>generator</span><span style=3D"color:#080">&l=
t;char32_t></span><span style=3D"color:#000"> unicode_tolower</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range</span=
><span style=3D"color:#660">&&</span><span style=3D"color:#000"> ch=
ars</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><b=
r><br></span><span style=3D"color:#008">template</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color:#=
008">typename</span><span style=3D"color:#000"> </span><span style=3D"color=
:#606">Char32Range</span><span style=3D"color:#660">></span><span style=
=3D"color:#000"><br>generator</span><span style=3D"color:#080"><char>=
</span><font color=3D"#000000"><span style=3D"color:#000"> encode_utf8</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#606">Char32Range=
</span><span style=3D"color:#660">&&</span><span style=3D"color:#00=
0"> chars</span><span style=3D"color:#660">);</span></font></div></code></d=
iv><br>Then you could compose them like so:</div><div><br></div><div><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px;word-wrap:break-word"><code><div><font col=
or=3D"#660066"><span style=3D"color:#008">template</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#606">Utf8Range</span><span style=3D"color:#660">></span><span style=
=3D"color:#000"><br>generator</span><span style=3D"color:#080"><char>=
</span><span style=3D"color:#000"> utf8_tolower</span><span style=3D"color:=
#660">(</span><span style=3D"color:#606">Utf8Range</span><span style=3D"col=
or:#660">&&</span><span style=3D"color:#000"> utf8bytes</span><span=
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span=
style=3D"color:#008">return</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 encode_utf8</span><span style=3D"color:#660">(</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 unicode_tolower</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 unicode_normalize<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 decode_utf8</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">forward</span><span style=3D"color:#=
660"><</span><span style=3D"color:#606">Utf8Range</span><span style=3D"c=
olor:#660">>(</span><span style=3D"color:#000">utf8by<wbr>tes</span><spa=
n style=3D"color:#660">)))));</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">}</span></font></div></code></div><br>And then, i=
f you want an output iterator version:</div><div><br></div><div><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px;word-wrap:break-word"><code><div><font color=
=3D"#660066"><span style=3D"color:#008">template</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color:#=
008">typename</span><span style=3D"color:#000"> </span><span style=3D"color=
:#606">Utf8Range</span><span style=3D"color:#660">,</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">typename</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Out</span><span style=3D"col=
or:#660">></span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#606">Out</span><span style=3D"color:#000"> utf_tolower</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#606">Utf8Range</span><span =
style=3D"color:#660">&&</span><span style=3D"color:#000"> utf8bytes=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#606">Out</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">out</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">copy</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">utf8_tolower</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">fo<wbr>rward</span><span style=3D"color:#660">&=
lt;</span><span style=3D"color:#606">Utf8Range</span><span style=3D"color:#=
660">>(</span><span style=3D"color:#000">utf8bytes</span><span style=3D"=
color:#660">),</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">out</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br></span><span style=3D"color:#660">}</span></font></div></code></d=
iv><br>So, my point, I think, is that I think it's better to implement =
algorithms like this first as range adaptors and then put an output iterato=
r interface on top rather than doing it the other way around.</div><div><br=
>On Thursday, 4 January 2018 09:31:51 UTC+13, Dimitrij Mijoski 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"><div><div><div><div><di=
v><div><div>From what i see std::view is the range equivalent of <b>copy_if=
</b> (or remove_copy_if with negated predicate). The range views described =
in the document are not always applicable.<br><br></div>Consider a more rea=
l world example.<br></div>Input, a UTF-8 narrow char sequence<br></div>Algo=
rithm 1: UTF-8 decoder, outputs a char32_t sequence<br></div>Algorithm 2: U=
nicode normalization, char32 to char32 sequence<br></div>Algorithm 3: ToLow=
er, similar<br></div>Algorithm 4: UTF-32 to UTF-8, char32 to narrow char se=
quence<br></div><br>These are all complex algorithms (e.g. Finite state mac=
hines that output a character only when some valid state is reached) and no=
ne of the standard iterating primitives like map/filter/reduce apply.<br><d=
iv><div><br></div><div>It would be a good idea to implement these algorithm=
s once in generic form "algo(first, last, out)" and then reuse th=
em in strings, vectors, maybe wrap them as generator etc.<br></div></div><d=
iv><br><div class=3D"gmail_quote">On Wed, Jan 3, 2018 at 8:34 PM, Toby Alls=
opp <span dir=3D"ltr"><<a rel=3D"nofollow">to...@mi6.gen.nz</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">You can get th=
e chaining you want using view::filter as decribed in=C2=A0<a href=3D"http:=
//www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0789r1.pdf" rel=3D"nofo=
llow" target=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.c=
om/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpap=
ers%2F2017%2Fp0789r1.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEbE2zPfzXc=
7G2A89exP29GcPM9ww';return true;" onclick=3D"this.href=3D'http://ww=
w.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2F=
docs%2Fpapers%2F2017%2Fp0789r1.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
EbE2zPfzXc7G2A89exP29GcPM9ww';return true;">http://www.open-std.org/<wb=
r>jtc1/sc22/wg21/docs/papers/<wbr>2017/p0789r1.pdf</a>.<div><br></div><div>=
But if you want to be able to adapt existing algorithms that take an output=
iterator so that they return a Range (such as a generator) then you're=
going to need something that acts as an output iterator and also acts as (=
or can convert to) a Range (because the algorithms generally return one pas=
t the last iterator they wrote to.</div><div><br></div><div>To make it work=
without a temporary, the output iterator (yielder in your example) would n=
eed to own the elements that have been written to it, which violates one of=
the characteristics of iterators, i.e. that they are cheap (O(1)) to copy.=
However, I guess it could be made to work. You don't need coroutines f=
or this, just a weird iterator type that stores a container and either also=
has begin and end members or has a conversion to something that does (such=
as the container it used to store the written elements).</div><div><br></d=
iv><div>Cheers,</div><div>Toby.</div><div><div><div><br>On Thursday, 4 Janu=
ary 2018 08:15:45 UTC+13, Dimitrij Mijoski wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr">With the addition of coroutines and generat=
ors we should also allow to=20
easily convert generic algorithm (that outputs into itrator/range) to=20
generator. The main motivation is to chain multiple algorithms without=20
having intermediate storage.<br><br>For example:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px"><code><div><div><span><span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
lass</span><span style=3D"color:rgb(0,0,0)"> T </span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(0,=
0,0)"> remove_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(0,0,=
0)"> first</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">InputIt<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">last</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">OutputIt=
</span><span style=3D"color:rgb(0,0,0)"> d_first</span><span style=3D"color=
:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span=
style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"co=
lor:rgb(0,0,0)"> value </span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(102,102,0)"><</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">InputIt</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">OutputIt</span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,0,102)">OutputIt</span><span style=3D"color:rgb(0,0,0)"> unique_copy</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(10=
2,0,102)">InputIt</span><span style=3D"color:rgb(0,0,0)"> first</span><span=
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">InputIt</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">last</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">OutputIt</span><span style=3D"col=
or:rgb(0,0,0)"> d_first</span><span style=3D"color:rgb(102,102,0)">);</span=
><span style=3D"color:rgb(0,0,0)"><br><br><br></span><span style=3D"color:r=
gb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span><span s=
tyle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br=
></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)=
"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)">1</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">11</=
span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136,0)">=
<int></span><span style=3D"color:rgb(0,0,0)"> tmp</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(136,0,0)">// GOAL, eliminate this temporary</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 remove=
_copy</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,136)">begin</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)=
">),</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">end</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,0)">v</span><span style=3D"color:rgb(102,102,0)">),</s=
pan><span style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><spa=
n style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(0,102,102)">5</span><span style=3D"color:r=
gb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 =C2=
=A0 vector</span><span style=3D"color:rgb(0,136,0)"><int></span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">out<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</spa=
n><span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">tmp</span><sp=
an style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"=
> back_inserter</span><span style=3D"color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">)=
);</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span></span><=
/span><span><p><span><span></span></span></p></span></div></div></code></di=
v><br>Up to C++17, the only way to achieve the goal is to create an <b>sepr=
ate iterator, e.g. class RemoveIterator</b> that accepts a pair of iterator=
s, and then put that as input into <b>unique_copy. </b>Writing custom itera=
tors is not the most pleasant thing because iterators are kind of simulatio=
n of generators.<br><br>Can we achieve something like this:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><code><span><span><span style=3D=
"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> main</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(=
0,136,0)"><int></span><span style=3D"color:rgb(0,0,0)"> v</span><span=
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)=
">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">1</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)"=
>5</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">,</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)=
">11</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0)">=C2=A0 =C2=A0 <b=
r>=C2=A0 =C2=A0 auto gen =3D remove_copy</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">begin</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">end</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">v</span><span s=
tyle=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)"> yi=
elder<int>{}</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">5<=
/span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rg=
b(0,0,0)"><br><br>=C2=A0 =C2=A0 vector</span><span style=3D"color:rgb(0,136=
,0)"><int></span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">out</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 unique_copy</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">begin</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=
=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)"=
>end</span><span style=3D"color:rgb(102,102,0)">(gen</span><span style=3D"c=
olor:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">),</span><span=
style=3D"color:rgb(0,0,0)"> back_inserter</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">out</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br></span></span></span></code><span style=3D"color:rgb(102,102,0)=
"></span></div></code></div></div>
</blockquote></div></div></div></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</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/e8de40c2-ee82-484f-93a0-f88cf5076bf4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;" on=
click=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/e8de40c2-ee82-484f-93a0-f88cf5076bf4%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/e8de40c2-ee82-484f-<wbr>93a0-=
f88cf5076bf4%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></blockquote></div></blockquote></div></div></bloc=
kquote></div></blockquote></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/14f721d0-e69f-4075-9ce0-bf4eae12b1a3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/14f721d0-e69f-4075-9ce0-bf4eae12b1a3=
%40isocpp.org</a>.<br />
------=_Part_3539_1060509906.1515098185803--
------=_Part_3538_468820411.1515098185801--
.