Topic: constexpr for loop?


Author: Evan Teran <evan.teran@gmail.com>
Date: Sat, 24 Jun 2017 17:12:58 -0700 (PDT)
Raw View
------=_Part_1416_424388798.1498349578809
Content-Type: multipart/alternative;
 boundary="----=_Part_1417_1036742248.1498349578810"

------=_Part_1417_1036742248.1498349578810
Content-Type: text/plain; charset="UTF-8"

I was just thinking the other day. Now that we are getting constexpr if,
what else could we allow at compile time? What occurs to me is that we
could have a nice compile time means to do loop unrolling. What I imagine
is something like this:


constexpr for(int i = 0; i < 4; ++i) {
    whatever();
}


would cause the compile to simply emit:

whatever();
whatever();
whatever();
whatever();

Obviously the loop bounds would have to be trivially known at compile time
for this to work, and should throw a hard error if it isn't. Many compilers
already are doing this analysis that would enable this, so why not make
that analysis able to be leveraged by the developer?

I know that the conventional wisdom is to just write the loop, and if the
compiler deems it optimal to unroll the loop, then it will. But sometimes,
people just know better.

I can imagine versions of many algorithms that are functionally identical
the standard ones, but allow the user to specify how much to unroll via
template parameters, like this (parden any typos):

namespace unrolled {

template <int N, class In, class Size, class F>
F for_each_n(In first, Size Count, F fn) {
    Size rounded = (count / N) * N; // round count down to nearest multiple
of N
    Size i = 0;


    // do as much as possible in chunks of unrolled size N
    while(i < rounded) {
        constexpr for(int j = 0; j < N; ++j) {
            fn(first[j]);
        }
        i += N;
    }


    while(i < count) {
        fn(first[i++]);
    }
}

}

Which would enable code like this:

unrolled::for_each_n<3>(std::begin(arr), 30, [](auto elem) {
    // do whatever with elem
}


It would be functionally the same as a regular std::for_each_n, but
unrolled into blocks of size 3 as much as possible.

Thoughts? Is this just not worth the effort?
Evan

--
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/46c1d5fc-6215-44f5-be84-651085690b0d%40isocpp.org.

------=_Part_1417_1036742248.1498349578810
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I was just thinking the other day. Now that we are getting=
 constexpr if, what else could we allow at compile time? What occurs to me =
is that we could have a nice compile time means to do loop unrolling. What =
I imagine is something like this:<br><br><br><div class=3D"prettyprint" sty=
le=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187=
); border-style: solid; border-width: 1px; word-wrap: break-word;"><code cl=
ass=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">for</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> i </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">4</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">++</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">i</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 style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 whatever</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"styled-by-prettify">}</span></div></code></div><div><br></div><div><br>=
</div><div>would cause the compile to simply emit:<br><br></div><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">whatever</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>whatever</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>whatever</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>whatever</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">();</span></div></code></div><div><br>=
</div><div>Obviously the loop bounds would have to be trivially known at co=
mpile time for this to work, and should throw a hard error if it isn&#39;t.=
 Many compilers already are doing this analysis that would enable this, so =
why not make that analysis able to be leveraged by the developer?</div><div=
><br>I know that the conventional wisdom is to just write the loop, and if =
the compiler deems it optimal to unroll the loop, then it will. But sometim=
es, people just know better.</div><div><br></div><div>I can imagine version=
s of many algorithms that are functionally identical the standard ones, but=
 allow the user to specify how much to unroll via template parameters, like=
 this (parden any typos):<br><br><div class=3D"prettyprint" style=3D"backgr=
ound-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-st=
yle: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prett=
yprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D=
"styled-by-prettify">namespace</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> unrolled </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">template</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&l=
t;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> N</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: #0=
08;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">In</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">class<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Size</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> F</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>F for_each_n</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">In</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> first</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Size</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">Count</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> F fn</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 style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>Size</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> roun=
ded </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</s=
pan><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: #000;" class=3D"styled-by-prettify">count </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">/</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> N</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</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: #000;" class=3D"styled-by-prettify"> N<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// round count down to neare=
st multiple of N</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled=
-by-prettify">Size</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br><br><br>=C2=A0 =C2=A0 </span>=
<span style=3D"color: #800;" class=3D"styled-by-prettify">// do as much as =
possible in chunks of unrolled size N</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">while</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">i </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> rounded</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><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 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>constexpr</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">for</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> j </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> j </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> N</span><s=
pan 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 style=3D"color: #000;"=
 class=3D"styled-by-prettify">j</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">)</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: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fn</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">first</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">[</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">j</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 =C2=A0 </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 i </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">+=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> N</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">while</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">i </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> co=
unt</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</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"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 fn=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">first</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">++]);</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span></div></code></div><div><br></div>Which would enable code=
 like this:<br><br></div><div class=3D"prettyprint" style=3D"background-col=
or: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: sol=
id; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-=
by-prettify">unrolled</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">for_each_n</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #066;" class=3D"styled-by-prettify">3</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">begin</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">arr</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">),</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">30</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">[](</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> elem</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 style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// do whatever with elem</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">}</span></div></code></div><div><br></div><div><=
br></div><div>It would be functionally the same as a regular std::for_each_=
n, but unrolled into blocks of size 3 as much as possible.</div><div><br></=
div><div>Thoughts? Is this just not worth the effort?</div><div>Evan</div><=
/div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/46c1d5fc-6215-44f5-be84-651085690b0d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/46c1d5fc-6215-44f5-be84-651085690b0d=
%40isocpp.org</a>.<br />

------=_Part_1417_1036742248.1498349578810--

------=_Part_1416_424388798.1498349578809--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 24 Jun 2017 21:06:32 -0700 (PDT)
Raw View
------=_Part_1368_1885285647.1498363592409
Content-Type: multipart/alternative;
 boundary="----=_Part_1369_1829644060.1498363592409"

------=_Part_1369_1829644060.1498363592409
Content-Type: text/plain; charset="UTF-8"

On Saturday, June 24, 2017 at 8:12:58 PM UTC-4, Evan Teran wrote:
>
> I was just thinking the other day. Now that we are getting constexpr if,
> what else could we allow at compile time? What occurs to me is that we
> could have a nice compile time means to do loop unrolling.
>

No. If we're going to have `constexpr for`, then it should serve an actual
semantic purpose, not merely be some syntactic sugar for a loop unrolling
compiler hint.

After all, we didn't add `if constexpr` just so that we could make sure the
condition was checked at compile-time instead of runtime. It exists to
allow us to write code that would otherwise be il-formed in the not-taken
branch. An optimizer can choose to check a condition at compile-time; an
optimizer cannot choose to pretend that il-formed code is valid. You need
actual syntax to make it so.

There have been several ideas and even proposals for `constexpr for`-type
things that offer actual features, things the optimizer couldn't do. You
should look at them.

--
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/e1dd7a42-f977-4f2d-9758-6c429389ce0a%40isocpp.org.

------=_Part_1369_1829644060.1498363592409
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Saturday, June 24, 2017 at 8:12:58 PM UTC-4, Evan Teran=
 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">I was =
just thinking the other day. Now that we are getting constexpr if, what els=
e could we allow at compile time? What occurs to me is that we could have a=
 nice compile time means to do loop unrolling.</div></blockquote><div><br>N=
o. If we&#39;re going to have `constexpr for`, then it should serve an actu=
al semantic purpose, not merely be some syntactic sugar for a loop unrollin=
g compiler hint.<br><br>After all, we didn&#39;t add `if constexpr` just so=
 that we could make sure the condition was checked at compile-time instead =
of runtime. It exists to allow us to write code that would otherwise be il-=
formed in the not-taken branch. An optimizer can choose to check a conditio=
n at compile-time; an optimizer cannot choose to pretend that il-formed cod=
e is valid. You need actual syntax to make it so.<br><br>There have been se=
veral ideas and even proposals for `constexpr for`-type things that offer a=
ctual features, things the optimizer couldn&#39;t do. You should look at th=
em.</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e1dd7a42-f977-4f2d-9758-6c429389ce0a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e1dd7a42-f977-4f2d-9758-6c429389ce0a=
%40isocpp.org</a>.<br />

------=_Part_1369_1829644060.1498363592409--

------=_Part_1368_1885285647.1498363592409--

.


Author: Evan Teran <evan.teran@gmail.com>
Date: Sat, 24 Jun 2017 23:18:12 -0700 (PDT)
Raw View
------=_Part_1351_26538043.1498371492315
Content-Type: multipart/alternative;
 boundary="----=_Part_1352_719765249.1498371492315"

------=_Part_1352_719765249.1498371492315
Content-Type: text/plain; charset="UTF-8"

That's fair enough, but I think that unrolling is just one of the things
you could do with this, so that was the first example I gave. I could also
imagine things like this:

constexpr for(int i = 0; i < 4; ++i) {
    templated_func<i>();
}

which is more that just unrolling hinting. It is actually instantiating 4
instances of a template at compile time. Of course you can do all of these
things with template recursion, but that gets messy really quickly.



On Sunday, June 25, 2017 at 12:06:32 AM UTC-4, Nicol Bolas wrote:
>
> On Saturday, June 24, 2017 at 8:12:58 PM UTC-4, Evan Teran wrote:
>>
>> I was just thinking the other day. Now that we are getting constexpr if,
>> what else could we allow at compile time? What occurs to me is that we
>> could have a nice compile time means to do loop unrolling.
>>
>
> No. If we're going to have `constexpr for`, then it should serve an actual
> semantic purpose, not merely be some syntactic sugar for a loop unrolling
> compiler hint.
>
> After all, we didn't add `if constexpr` just so that we could make sure
> the condition was checked at compile-time instead of runtime. It exists to
> allow us to write code that would otherwise be il-formed in the not-taken
> branch. An optimizer can choose to check a condition at compile-time; an
> optimizer cannot choose to pretend that il-formed code is valid. You need
> actual syntax to make it so.
>
> There have been several ideas and even proposals for `constexpr for`-type
> things that offer actual features, things the optimizer couldn't do. You
> should look at them.
>

--
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/f8cfe7d2-83bb-4b30-af65-2a7f0d4b1081%40isocpp.org.

------=_Part_1352_719765249.1498371492315
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">That&#39;s fair enough, but I think that unrolling is just=
 one of the things you could do with this, so that was the first example I =
gave. I could also imagine things like this:<br><br><div class=3D"prettypri=
nt" 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 class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">for</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> i </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">4</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">++</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">i</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 templated_func</span><span style=
=3D"color: #080;" class=3D"styled-by-prettify">&lt;i&gt;</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span></div></code></div><div><span sty=
le=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: =
rgb(102, 102, 0);"><br></span>which is more that just unrolling hinting. It=
 is actually instantiating 4 instances of a template at compile time. Of co=
urse you can do all of these things with template recursion, but that gets =
messy really quickly.<br><br><br><br>On Sunday, June 25, 2017 at 12:06:32 A=
M UTC-4, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr">On Saturday, June 24, 2017 at 8:12:58 PM UTC-4, Evan Teran wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I was just thi=
nking the other day. Now that we are getting constexpr if, what else could =
we allow at compile time? What occurs to me is that we could have a nice co=
mpile time means to do loop unrolling.</div></blockquote><div><br>No. If we=
&#39;re going to have `constexpr for`, then it should serve an actual seman=
tic purpose, not merely be some syntactic sugar for a loop unrolling compil=
er hint.<br><br>After all, we didn&#39;t add `if constexpr` just so that we=
 could make sure the condition was checked at compile-time instead of runti=
me. It exists to allow us to write code that would otherwise be il-formed i=
n the not-taken branch. An optimizer can choose to check a condition at com=
pile-time; an optimizer cannot choose to pretend that il-formed code is val=
id. You need actual syntax to make it so.<br><br>There have been several id=
eas and even proposals for `constexpr for`-type things that offer actual fe=
atures, things the optimizer couldn&#39;t do. You should look at them.</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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f8cfe7d2-83bb-4b30-af65-2a7f0d4b1081%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f8cfe7d2-83bb-4b30-af65-2a7f0d4b1081=
%40isocpp.org</a>.<br />

------=_Part_1352_719765249.1498371492315--

------=_Part_1351_26538043.1498371492315--

.


Author: peetpaul69@gmail.com
Date: Sun, 25 Jun 2017 13:39:11 -0700 (PDT)
Raw View
------=_Part_1507_901239115.1498423151817
Content-Type: multipart/alternative;
 boundary="----=_Part_1508_681461918.1498423151818"

------=_Part_1508_681461918.1498423151818
Content-Type: text/plain; charset="UTF-8"

It seems that this could be really useful, especially for static reflection.

And actually, there is a fork of clang by Andrew Sutton which basically
implements the "constexpr" (evaluation/unrolling at compile-time) loop:

Here is a demo: https://godbolt.org/g/maV08o

More
info: https://www.reddit.com/r/cpp/comments/68ljh4/there_is_no_interface_keyword_in_c_herbsutter/

On Sunday, June 25, 2017 at 2:12:58 AM UTC+2, Evan Teran wrote:
>
> I was just thinking the other day. Now that we are getting constexpr if,
> what else could we allow at compile time? What occurs to me is that we
> could have a nice compile time means to do loop unrolling. What I imagine
> is something like this:
>
>
> constexpr for(int i = 0; i < 4; ++i) {
>     whatever();
> }
>
>
> would cause the compile to simply emit:
>
> whatever();
> whatever();
> whatever();
> whatever();
>
> Obviously the loop bounds would have to be trivially known at compile time
> for this to work, and should throw a hard error if it isn't. Many compilers
> already are doing this analysis that would enable this, so why not make
> that analysis able to be leveraged by the developer?
>
> I know that the conventional wisdom is to just write the loop, and if the
> compiler deems it optimal to unroll the loop, then it will. But sometimes,
> people just know better.
>
> I can imagine versions of many algorithms that are functionally identical
> the standard ones, but allow the user to specify how much to unroll via
> template parameters, like this (parden any typos):
>
> namespace unrolled {
>
> template <int N, class In, class Size, class F>
> F for_each_n(In first, Size Count, F fn) {
>     Size rounded = (count / N) * N; // round count down to nearest
> multiple of N
>     Size i = 0;
>
>
>     // do as much as possible in chunks of unrolled size N
>     while(i < rounded) {
>         constexpr for(int j = 0; j < N; ++j) {
>             fn(first[j]);
>         }
>         i += N;
>     }
>
>
>     while(i < count) {
>         fn(first[i++]);
>     }
> }
>
> }
>
> Which would enable code like this:
>
> unrolled::for_each_n<3>(std::begin(arr), 30, [](auto elem) {
>     // do whatever with elem
> }
>
>
> It would be functionally the same as a regular std::for_each_n, but
> unrolled into blocks of size 3 as much as possible.
>
> Thoughts? Is this just not worth the effort?
> Evan
>

--
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/b4bd172a-05c9-4a92-83fa-beba24150472%40isocpp.org.

------=_Part_1508_681461918.1498423151818
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">It seems that this could be really useful, especially for =
static reflection.<div><br></div><div>And actually, there is a fork of clan=
g by Andrew Sutton which basically implements the &quot;constexpr&quot; (ev=
aluation/unrolling at compile-time) loop:</div><div><br></div><div>Here is =
a demo:=C2=A0https://godbolt.org/g/maV08o</div><div><br></div><div>More inf=
o:=C2=A0https://www.reddit.com/r/cpp/comments/68ljh4/there_is_no_interface_=
keyword_in_c_herbsutter/<br><br>On Sunday, June 25, 2017 at 2:12:58 AM UTC+=
2, Evan Teran wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">I was just thinking the other day. Now that we are getting constex=
pr if, what else could we allow at compile time? What occurs to me is that =
we could have a nice compile time means to do loop unrolling. What I imagin=
e is something like this:<br><br><br><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><span style=3D"color:#008">constexpr</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">for</span><=
span style=3D"color:#660">(</span><span style=3D"color:#008">int</span><spa=
n style=3D"color:#000"> i </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"> i </span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">4</span><span style=3D"color:#660">;</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">++</span><span style=3D"color=
:#000">i</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 =C2=A0 whatever</span><span style=3D"color:#660">();</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#660">}</span></div></co=
de></div><div><br></div><div><br></div><div>would cause the compile to simp=
ly emit:<br><br></div><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word"><code><div><span style=3D"color:#000">whatever</span><span style=3D=
"color:#660">();</span><span style=3D"color:#000"><br>whatever</span><span =
style=3D"color:#660">();</span><span style=3D"color:#000"><br>whatever</spa=
n><span style=3D"color:#660">();</span><span style=3D"color:#000"><br>whate=
ver</span><span style=3D"color:#660">();</span></div></code></div><div><br>=
</div><div>Obviously the loop bounds would have to be trivially known at co=
mpile time for this to work, and should throw a hard error if it isn&#39;t.=
 Many compilers already are doing this analysis that would enable this, so =
why not make that analysis able to be leveraged by the developer?</div><div=
><br>I know that the conventional wisdom is to just write the loop, and if =
the compiler deems it optimal to unroll the loop, then it will. But sometim=
es, people just know better.</div><div><br></div><div>I can imagine version=
s of many algorithms that are functionally identical the standard ones, but=
 allow the user to specify how much to unroll via template parameters, like=
 this (parden any typos):<br><br><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><span style=3D"color:#008">namespace</span><s=
pan style=3D"color:#000"> unrolled </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"><br><br></span><span style=3D"color:#008">temp=
late</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#008">int</span><span style=3D"color:#000"> N=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">class</span><span style=3D"color:#000"> </span=
><span style=3D"color:#606">In</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">class</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Size</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">class</span><span style=3D"color:#000"> F</span><span style=
=3D"color:#660">&gt;</span><span style=3D"color:#000"><br>F for_each_n</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#606">In</span><s=
pan style=3D"color:#000"> first</span><span style=3D"color:#660">,</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#606">Size</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Count</span><span=
 style=3D"color:#660">,</span><span style=3D"color:#000"> F fn</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 =C2=A0 </span=
><span style=3D"color:#606">Size</span><span style=3D"color:#000"> rounded =
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">count </s=
pan><span style=3D"color:#660">/</span><span style=3D"color:#000"> N</span>=
<span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">*</span><span style=3D"color:#000"> N</span><span sty=
le=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D=
"color:#800">// round count down to nearest multiple of N</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#606">Size</s=
pan><span style=3D"color:#000"> i </span><span style=3D"color:#660">=3D</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br><br><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#800">// do as much as possible in c=
hunks of unrolled size N</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 </span><span style=3D"color:#008">while</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">i </span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000"> rounded</span><span style=3D"color:#660">=
)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">for</span><span style=3D"color:#660">(</span><span =
style=3D"color:#008">int</span><span style=3D"color:#000"> j </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#066">0</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> j </span><span style=3D"color:#660">&lt;</span><span style=3D"=
color:#000"> N</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">++</span><span style=3D"color:#0=
00">j</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 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fn</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">first</span><span style=3D"color:#660=
">[</span><span style=3D"color:#000">j</span><span style=3D"color:#660">]);=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 i </span><span style=3D"color:#660">+=3D</span><span styl=
e=3D"color:#000"> N</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br><br><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">while</span><span style=3D"color:#660">(</span><span style=3D"col=
or:#000">i </span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#000"> count</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 fn</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#000">first</span><span style=3D"color:#660">[</sp=
an><span style=3D"color:#000">i</span><span style=3D"color:#660">++]);</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#660">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br><br></span><span style=3D"color:=
#660">}</span></div></code></div><div><br></div>Which would enable code lik=
e this:<br><br></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><span style=3D"color:#000">unrolled</span><span style=3D"=
color:#660">::</span><span style=3D"color:#000">for_each_n</span><span styl=
e=3D"color:#660">&lt;</span><span style=3D"color:#066">3</span><span style=
=3D"color:#660">&gt;(</span><span style=3D"color:#000">std</span><span styl=
e=3D"color:#660">::</span><span style=3D"color:#008">b<wbr>egin</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#000">arr</span><span st=
yle=3D"color:#660">),</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">30</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">[](</span><span style=3D"col=
or:#008">auto</span><span style=3D"color:#000"> elem</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#800">// do whatever with elem</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#660">}</span></div></code></div><div><br>=
</div><div><br></div><div>It would be functionally the same as a regular st=
d::for_each_n, but unrolled into blocks of size 3 as much as possible.</div=
><div><br></div><div>Thoughts? Is this just not worth the effort?</div><div=
>Evan</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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b4bd172a-05c9-4a92-83fa-beba24150472%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b4bd172a-05c9-4a92-83fa-beba24150472=
%40isocpp.org</a>.<br />

------=_Part_1508_681461918.1498423151818--

------=_Part_1507_901239115.1498423151817--

.