Topic: Allowing variadic templates to match specific type at


Author: =?UTF-8?Q?Micha=C5=82_Dominiak?= <griwes@griwes.info>
Date: Fri, 12 Apr 2013 10:50:05 -0700 (PDT)
Raw View
------=_Part_306_12522982.1365789005715
Content-Type: text/plain; charset=ISO-8859-1

Hello,

I'd like to propose an extension to variadic templates as a workaround for
a problem I've stumbled upon today.

Let's say we have a function variadic template, and we want it to be
callable with numerous types - including tuples,
which should be expanded and passed to that function again. It would be
obviously useful only in highly generic code,
and I wanted to get such effect today, as I've mentioned (having a way to
do such forwarding allows one to
use data structures without reflection and without shenanigans like
Boost.Fusion, thanks to uniform initialization it
may call either aggregate initialization or constructor using the same
syntax, which is a huge win. Of course, it may
introduce some problems, as uniform initialization isn't perfect, but it's
far better than, say, Boost.Fusion).

So, the first thing that comes to mid is something like this
(pseudocode-ish, of course):

template<typename...>
struct foo { ... };

template<typename... Args1, typename... TupleTypes, typename... Args2>
struct foo<Args1..., std::tuple<TupleTypes...>, Args2...>
{
    static void bar(const Args1 &... args1, const std::tuple<TupleTypes...>
& t, const Args2... args2)
    {
        // call foo<Args1..., TupleTypes..., Args2...>::bar(args1..., [
expanded tuple ], args2...);
        // I didn't want to introduce index generation into this, so I left
it in this form
    }
};

This would be easiest possible way to do it, at least conceptually. For
example, for `foo<int, tuple<int, float>, string, float>`,
compiler would detect Args1 = { int }, TupleTypes = { int, float }, Args2 =
{ string, float }, that is, until something matches
the "concrete" parameter, everything is added to Args1, and after something
matches - rest is added to Args2. If there are
two tuples in `foo`'s template parameters, it would expand them both -
match first, expand it, invoke foo again, this time with
single tuple, which was previously matched into Args2.

This would certainly add some complexity to the compiler, especially if,
say, two consecutive "concrete" parameters were
allowed, but it definitely eases applying some operation to parameters of
only some types, without boilerplate. Of course,
this example problem can also be solved without such feature - turn
everything into one big tuple, expand it, profit!, but,
again, it adds boilerplate (I'll probably have to implement it for the code
I'm writing, but I will never like this solution). With
other operations, like "dereference every optional parameter" I'm doing
too, it's much easier, just create a helper function
that dereferences optionals and does nothing to other types, but still, so
much boilerplate.

What do you think?

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



------=_Part_306_12522982.1365789005715
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hello,<div><br></div><div>I'd like to propose an extension to variadic temp=
lates as a workaround for a problem I've stumbled upon today.</div><div><br=
></div><div>Let's say we have a function variadic template, and we want it =
to be callable with numerous types - including tuples,</div><div>which shou=
ld be expanded and passed to that function again. It would be obviously use=
ful only in highly generic code,&nbsp;</div><div>and I wanted to get such e=
ffect today, as I've mentioned (having a way to do such forwarding allows o=
ne to</div><div>use data structures without reflection and without shenanig=
ans like Boost.Fusion, thanks to uniform initialization it</div><div>may ca=
ll either aggregate initialization or constructor using the same syntax, wh=
ich is a huge win. Of course, it may&nbsp;</div><div>introduce some problem=
s, as uniform initialization isn't perfect, but it's far better than, say, =
Boost.Fusion).</div><div><br></div><div>So, the first thing that comes to m=
id is something like this (pseudocode-ish, of course):</div><div><br></div>=
<div>template&lt;typename...&gt;</div><div>struct foo { ... };</div><div><b=
r></div><div>template&lt;typename... Args1, typename... TupleTypes, typenam=
e... Args2&gt;</div><div>struct foo&lt;Args1..., std::tuple&lt;TupleTypes..=
..&gt;, Args2...&gt;</div><div>{</div><div>&nbsp; &nbsp; static void bar(con=
st Args1 &amp;... args1, const std::tuple&lt;TupleTypes...&gt; &amp; t, con=
st Args2... args2)</div><div>&nbsp; &nbsp; {</div><div>&nbsp; &nbsp; &nbsp;=
 &nbsp; // call foo&lt;Args1..., TupleTypes..., Args2...&gt;::bar(args1...,=
 [ expanded tuple ], args2...);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; // I =
didn't want to introduce index generation into this, so I left it in this f=
orm</div><div>&nbsp; &nbsp; }</div><div>};</div><div><br></div><div>This wo=
uld be easiest possible way to do it, at least conceptually. For example, f=
or `foo&lt;int, tuple&lt;int, float&gt;, string, float&gt;`,</div><div>comp=
iler would detect Args1 =3D { int }, TupleTypes =3D { int, float }, Args2 =
=3D { string, float }, that is, until something matches</div><div>the "conc=
rete" parameter, everything is added to Args1, and after something matches =
- rest is added to Args2. If there are</div><div>two tuples in `foo`'s temp=
late parameters, it would expand them both - match first, expand it, invoke=
 foo again, this time with</div><div>single tuple, which was previously mat=
ched into Args2.</div><div><br></div><div>This would certainly add some com=
plexity to the compiler, especially if, say, two consecutive "concrete" par=
ameters were</div><div>allowed, but it definitely eases applying some opera=
tion to parameters of only some types, without boilerplate. Of course,</div=
><div>this example problem can also be solved without such feature - turn e=
verything into one big tuple, expand it, profit!, but,</div><div>again, it =
adds boilerplate (I'll probably have to implement it for the code I'm writi=
ng, but I will never like this solution). With</div><div>other operations, =
like "dereference every optional parameter" I'm doing too, it's much easier=
, just create a helper function</div><div>that dereferences optionals and d=
oes nothing to other types, but still, so much boilerplate.</div><div><br><=
/div><div>What do you think?</div>

<p></p>

-- <br />
&nbsp;<br />
--- <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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_306_12522982.1365789005715--

.