Topic: statement folding on variadic templates parameters pack


Author: Sergey Vidyuk <sir.vestnik@gmail.com>
Date: Wed, 8 Jun 2016 07:14:50 -0700 (PDT)
Raw View
------=_Part_328_2142156276.1465395290253
Content-Type: multipart/alternative;
 boundary="----=_Part_329_274707728.1465395290254"

------=_Part_329_274707728.1465395290254
Content-Type: text/plain; charset=UTF-8

Expression folding on a variadic template parameters pack are great and
allows to write internal function stuff inside a function instead of
writing some recursive template code which is required to be moved outside
of the function. But when one want to repeat some statement for every
element of a parameter pack recursive templates or abusing of coma operator
folding are stil the only options. After facing this issue several times I
start to realize that it would be great to have the following extension to
the C++11 range-for syntax:

template<typename... L> void foo() {
    for (typename T: L...) {
        // do the stuff
    }
}

template<typename... A> void foo(A&& a) {
    for (const auto& arg: a...) {
        // do the stuff
    }
}

In both cases the loop is unrolled in compile time and it's body is
instantiate for each exact type in the same way as a body of template
function. Each instantiation of a body has it's own scope and there are no
outter scope polution posibility. Standard loop operators break and
continue should also be allowed for both cases and work in the same way as
in any runtime C++ loop.

It should also work for non-type parameter packs:

template<size_t... I> void foo() {
    for (auto i: I...) {/*the code goes here*/}
    // as well as
    for (size_t i: I...) {/*the code goes here*/}
}

which can be implemented right now as

template<size_t... I> void foo() {
    for (size_t i: {I...}) {/*the code goes here*/}
}

so this use case might not be really interresting.

I'm shure there were same idea duscussed somewhere in this list but I was
unable to find them. I've seen proposals to add index access to parameters
packs but there is no mechanism in the language to implement loop over
constexpr indexes so index access do not solve tasks of statement folding.
This proposal do not conflict with index access to a parameter packs.

As far as I know this syntax extension do not conflict with any other
language feature and seems to be easy to implement in compilers. It's
simple and convenient for average C++ programmers in contrast to recursive
templates and should have better compilation speed.

Motivating example:

template<typename... V>
class variant_ptr {
public:
    template<typename Func, typename... A>
    auto invoke(Func&& f, A&&... a) const {
        size_t idx = 0;
        for (typename T: V...) {
            if (type_idx_ == idx++)
                return std::invoke(std::forward<Func>(f),
reinterpret_cast<T*>(data_), std::forward<A>(a)...);
        }
        assert(false);
        throw std::logick_error("should never happen");
    }

private:
    void* data_;
    size_t type_idx_;
};

Just try to ask experienced C++ programmer who is not template
metaprogramming fan to write this in C++14 and check amount of boilerplate
code and its redability if he will finish this task.

Are there any objections agains such syntax for C++? Is it worth to try to
write proposal to add it?

Sergey Vidyuk

--
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/1e3daa7c-e10a-4589-8118-26f47bc1a0df%40isocpp.org.

------=_Part_329_274707728.1465395290254
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Expression folding on a variadic template parameters pack =
are great and allows to write internal function stuff inside a function ins=
tead of writing some recursive template code which is required to be moved =
outside of the function. But when one want to repeat some statement for eve=
ry element of a parameter pack recursive templates or abusing of coma opera=
tor folding are stil the only options. After facing this issue several time=
s I start to realize that it would be great to have the following extension=
 to the C++11 range-for syntax:<br><br><div class=3D"prettyprint" style=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 class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">template</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">typename</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> L</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span st=
yle=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 </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">for</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> L</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">...)</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:=
 #800;" class=3D"styled-by-prettify">// do the stuff</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </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></span><span style=3D"color: #=
660;" class=3D"styled-by-prettify"></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><br><code class=3D"prettyprint"><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> A</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(A&amp;&am=
p; a)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><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><span style=3D"color:=
 #000;" class=3D"styled-by-prettify">=C2=A0 =C2=A0 </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">for</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(const auto</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify"></span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">&amp; arg</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> a</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 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// =
do the stuff</span><span style=3D"color: #000;" class=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;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #000;" class=3D"styled-by-prettify"></spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></code></div>=
</code></div><br>In both cases the loop is unrolled in compile time and it&=
#39;s body is instantiate for each exact type in the same way as a body of =
template function. Each instantiation of a body has it&#39;s own scope and =
there are no outter scope polution posibility. Standard loop operators brea=
k and continue should also be allowed for both cases and work in the same w=
ay as in any runtime C++ loop.<br><br>It should also work for non-type para=
meter packs:<br><br><div class=3D"prettyprint" style=3D"background-color: r=
gb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; b=
order-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div =
class=3D"subprettyprint"><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">template&lt;size_t... I&gt; void foo() {<br>=C2=A0=C2=A0=C2=A0 </sp=
an><code class=3D"prettyprint"><span style=3D"color: #660;" class=3D"styled=
-by-prettify">for (auto i: I...) {/*the code goes here*/}</span></code><br>=
<span style=3D"color: #660;" class=3D"styled-by-prettify"><code class=3D"pr=
ettyprint"><span style=3D"color: #660;" class=3D"styled-by-prettify">=C2=A0=
=C2=A0=C2=A0 // as well as<br></span></code>=C2=A0=C2=A0=C2=A0 for (size_t =
i: I...) {/*the code goes here*/}<br>}<br></span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"></span></div></code></div><br>which can be =
implemented right now as<br><br><div class=3D"prettyprint" style=3D"backgro=
und-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-sty=
le: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pretty=
print"><div class=3D"subprettyprint"><span style=3D"color: #660;" class=3D"=
styled-by-prettify">template&lt;size_t... I&gt; void foo() {<br>=C2=A0=C2=
=A0=C2=A0 for (size_t i: {I...}) {</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><code class=3D"prettyprint"><code class=3D"prettypr=
int"><span style=3D"color: #660;" class=3D"styled-by-prettify">/*the code g=
oes here*/</span></code></code>}<br>}<br></span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"></span></div></code></div><br>so this use ca=
se might not be really interresting.<br><br>I&#39;m shure there were same i=
dea duscussed somewhere in this list but I was unable to find them. I&#39;v=
e seen proposals to add index access to parameters packs but there is no me=
chanism in the language to implement loop over constexpr indexes so index a=
ccess do not solve tasks of statement folding. This proposal do not conflic=
t with index access to a parameter packs.<br><br>As far as I know this synt=
ax extension do not conflict with any other language feature and seems to b=
e easy to implement in compilers. It&#39;s simple and convenient for averag=
e C++ programmers in contrast to recursive templates and should have better=
 compilation speed.<br><br>Motivating example:<br><br><div class=3D"prettyp=
rint" 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 class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">template&lt;typename... V&gt;<br>=
class variant_ptr {<br>public:<br>=C2=A0 =C2=A0 template&lt;typename Func, =
typename... A&gt;<br>=C2=A0 =C2=A0 auto invoke(Func&amp;&amp; f, A&amp;&amp=
;... a) const {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t idx =
=3D 0;<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 for (typename T: V...)=
 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (type_idx_ =3D=3D idx++)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return std::invoke(std::forwa=
rd&lt;Func&gt;(f), reinterpret_cast&lt;T*&gt;(data_), std::forward&lt;A&gt;=
(a)...);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 assert(false);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 throw std::logick_error(&quot;should never happen&quot;);<b=
r>=C2=A0=C2=A0=C2=A0 } =C2=A0 <br><br>private:<br>=C2=A0=C2=A0=C2=A0 void* =
data_;<br>=C2=A0=C2=A0=C2=A0 size_t type_idx_;<br>};<br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"></span></div></code></div><b=
r>Just try to ask experienced C++ programmer who is not template metaprogra=
mming fan to write this in C++14 and check amount of boilerplate code and i=
ts redability if he will finish this task.<br><br>Are there any objections =
agains such syntax for C++? Is it worth to try to write proposal to add it?=
<br><br>Sergey Vidyuk<br></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/1e3daa7c-e10a-4589-8118-26f47bc1a0df%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1e3daa7c-e10a-4589-8118-26f47bc1a0df=
%40isocpp.org</a>.<br />

------=_Part_329_274707728.1465395290254--

------=_Part_328_2142156276.1465395290253--

.