Topic: Going further with parameter packs: aliases,
Author: Alex B <devalexb@gmail.com>
Date: Fri, 22 Nov 2013 11:36:47 -0800 (PST)
Raw View
------=_Part_870_24339805.1385149007894
Content-Type: text/plain; charset=ISO-8859-1
Hi,
I have been working on several ideas that would fill several gaps and make
things much easier when dealing with parameter packs. Before going in with
a formal proposal, I first wanted to share my ideas. Feedback would be
greatly appreciated.
*Type pack alias*
A pack alias (templated or not) can be defined with a "using..." directive.
On the right hand side must be an unexpanded type pack. This unexpanded
type pack can come from an unexpanded parameter pack of a variadic template
or from another pack alias.
A pack alias can be expanded with the "..." operator in the same way as an
unexanded parameter pack of a variadic template.
The most basic (and useful) templated pack alias would be the following,
which allow creating packs on the fly:
template <class... T>
using... type_pack = T;
Usage example:
using... my_types = type_pack<int, char, double>;
using my_tuple = tuple<my_types...>;
*Variable pack*
Variable packs are the same as function parameter packs, except that they
can be declared anywhere a variable can be declared. There are two ways to
declare and initialize a variable pack.
The first one is by using an already defined type pack. If constructor
arguments are specified as single values, all the constructors of the
variables in the pack are called with those same arguments.
using... types = type_pack<int, char, double>;
types values1;
type_pack<int, char, double> values2;
types values3 = 10; // all 3 variables are initialized to 10
types values4(10); // same
types values5 = values2;
type_pack<double, double, double> values6 = values2;
//type_pack<int, char> values7 = values2; //error: mismatching pack sizes
template <class... T>
class C
{
T... values;
};
template <class... T>
void f(T... t)
{
T... t2 = t * 2;
}
A variable pack can also be declared without a defined type pack. In that
case, it must be initialized from another variable pack.
//double... values8; //error: unknown pack size
//double... values9 = 10.0; //error: unknown pack size
double... values10 = values2; // pack of 3 variables of type double
double... values11(values2); // same
auto... values12 = values2; // pack of 3 variables of types int, char and
double
template <class... T>
void g(T... t)
{
auto... t2 = t * 2;
}
Operations can be done on packs if all the unexpanded packs are of the same
size.
values10 = values11 * 2.0;
values11 += values10;
values11 = values10 + values11;
Single values can be used along with pack but only in operations in which
those single values are const.
double single_value = 1.0;
values10 *= single_value; //ok: rhs is const single_value
single_value *= values10; //error: lhs of operator*= cannot be const
void h(const double&, double&) {}
h(values10, values11); //ok: 2 packs of the same size (h will be called 3
times)
h(single_value, values10); //ok: first arg of h is const (h will be called
3 times, each time with the same single_value)
h(values10, single_value); //error: trying to pass a non-const single value
in an unexpanded context
*Variable template pack*
Variable packs should also work for variable templates.
The most basic (and useful) variable template packs would be an equivalent
to std::integer_sequence that would allow working directly with an integer
pack (instead of having to store that pack in a type).
template <class T, T... I>
constexpr T... integer_pack = I;
template <size_t... I>
constexpr size_t... index_pack = I;
template <class T, T N>
constexpr T... make_integer_pack = integer_pack<T, /* a sequence 0, 1, 2,
...., N-1 */>;
template <size_t N>
constexpr size_t... make_index_pack = make_integer_pack<size_t, N>;
template <class... T>
constexpr size_t... index_pack_for = make_index_pack<sizeof...(T)>;
With these variable template packs, additional utilies can be provided for
tuple-like classes:
// tuple_indices<T> is equivalenent to 0, 1, ..., tuple_size<T>::value - 1
template <class T>
constexpr size_t... tuple_indices = make_index_pack<tuple_size<T>::value>;
// tuple_elements<T> is equivalent to tuple_element_t<0, T>,
tuple_element_t<1, T>, ..., tuple_element_t<N-1, T>
template <class T>
using... tuple_elements = tuple_element_t<tuple_indices<T>, T>;
These are much more simpler to use than current workarounds requiring usage
of std::integer_sequence. Example of passing all elements of tuple t as
arguments to a function f:
template <class... Args>
void f(Args&&... args);
template <class Tuple>
void g(T&& t)
{
f(get<tuple_indices<T>>(forward<T>(t))...);
}
*Returning a pack from a function*
With pack variables comes the need for functions returning a pack of values.
The most basic function that could be defined is one returning a pack from
several values:
template <class... T>
decltype(auto)... make_pack(T&&... t) { return forward<T>(t); }
Usage example:
void g(int a, int b, int c, int d, int e, int f, int g, int h);
// Following functions forward all arguments to g by first multiplying them
by 2 and adding 3
void f(int a, int b, int c, int d, int e, int f, int g, int h)
{
// Old way
g(a*2 + 3, b*2 + 3, c*2 + 3, d*2 + 3, e*2 + 3, f*2 + 3, g*2 + 3, h*2 + 3);
// New way
g(make_pack(a, b, c, d, e, f, g, h)*2 + 3 ...);
}
Another usage would be a function returning all the values of a tuple-like
class:
// get_all(t) is equivalent to get<0>(t), get<1>(t), ..., get<N-1>(t)
template <class T>
constexpr decltype(auto)... get_all(T&& t) { return get<tuple_indices<T>>(
forward<T>(t)); }
Usage example (passing all elements of tuple t as arguments to a function
f):
template <class... T>
void f(T&&... t);
template <class Tuple>
void g(T&& t)
{
f(get_all(forward<T>(t))...);
}
*Expanding nested pack aliases*
Considering the following:
using... original = type_pack<T0, T1, /*...*/, TN>;
template <class... T>
using... alias = /*...*/;
using... a = alias<original...>;
using... b = alias<original>...;
The pack a is the result of applying the alias on the entire original pack.
The pack b is the result of applying the alias on each individual elements
of the original pack.
using... a = alias<T0, T1, /*...*/, TN>;
using... b = type_pack<alias<T0>..., alias<T1>..., /*...*/, alias<TN>...>;
When multiple aliases are used, the same rules can be applied successively
by considering the inner-most pack first.
The following example illustrates how the rules are applied when 2 aliases
are used on a pack.
using... orig = type_pack<T0, T1, /*...*/, TN>;
template <class... T>
using... a1 = /*...*/;
template <class... T>
using... a2 = /*...*/;
using... a = a1<a2<orig...>...>;
// same as: using... temp = a2<orig...>;
// using... a = a1<temp...>;
using... b = a1<a2<orig>... ...>;
// same as: using... temp = a2<orig>...;
// using... b = a1<temp...>;
using... c = a1<a2<orig...>>...;
// same as: using... temp = a2<orig...>;
// using... c = a1<temp>...;
using... d = a1<a2<orig>...>...;
// same as: using... temp = a2<orig>...;
// using... d = a1<temp>...;
//using... e = a1<a2<orig>>... ...;
// error
//using... f = a1<a2<orig... ...>>;
// error
Additional examples
struct A {};
struct B {};
template <class... T>
using... twice = type_pack<T..., T...>;
using... AB = type_pack<A, B>; // A, B
using... t1 = twice<AB...>; // A, B, A, B
using... t2 = type_pack<twice<AB...>...>; // A, B, A, B
using... t3 = twice<AB>...; // A, A, B, B
using... t4 = type_pack<twice<AB>... ...>; // A, A, B, B
using... t5 = twice<twice<AB...>...>; // A, B, A, B, A, B, A, B
using... t6 = twice<twice<AB>... ...>; // A, A, B, B, A, A, B, B
using... t7 = twice<twice<AB...>>...; // A, A, B, B, A, A, B, B
using... t8 = twice<twice<AB>...>...; // A, A, A, A, B, B, B, B
struct C {};
template <class... T>
using... add_c = type_pack<T..., C>;
using... u1 = add_c<AB...>; // A, B, C
using... u2 = add_c<AB>...; // A, C, B, C
using... u3 = add_c<add_c<AB...>...>; // A, B, C, C
using... u4 = add_c<add_c<AB>... ...>; // A, C, B, C, C
using... u5 = add_c<add_c<AB...>>...; // A, C, B, C, C, C
using... u6 = add_c<add_c<AB>...>...; // A, C, C, C, B, C, C, C
using... v1 = add_c<twice<AB...>...>; // A, B, A, B, C
using... v2 = add_c<twice<AB>... ...>; // A, A, B, B, C
using... v3 = add_c<twice<AB...>>...; // A, C, B, C, A, C, B, C
using... v4 = add_c<twice<AB>...>...; // A, C, A, C, B, C, B, C
using... w1 = twice<add_c<AB...>...>; // A, B, C, A, B, C
using... w2 = twice<add_c<AB>... ...>; // A, C, B, C, A, C, B, C
using... w3 = twice<add_c<AB...>>...; // A, A, B, B, C, C
using... w4 = twice<add_c<AB>...>...; // A, A, C, C, B, B, C, C
--
---
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/.
------=_Part_870_24339805.1385149007894
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi,</div><div> </div><div>I have been working on=
several ideas that would fill several gaps and make things much easie=
r when dealing with parameter packs. Before going in with a formal proposal=
, I first wanted to share my ideas. Feedback would be greatly appreciated.<=
/div><div><strong><font size=3D"4"></font></strong> </div><div><font s=
ize=3D"4"><strong>Type pack alias</strong></font></div><div> </div><di=
v>A pack alias (templated or not) can be defined with a "using..." directiv=
e. On the right hand side must be an unexpanded type pack. This unexpanded =
type pack can come from an unexpanded parameter pack of a variadic template=
or from another pack alias.</div><div> </div><p>A pack alias can be e=
xpanded with the "..." operator in the same way as an unexanded parameter p=
ack of a variadic template.</p><p>The most basic (and useful) templated pac=
k alias would be the following, which allow creating packs on the fly:</p><=
div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; b=
ackground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, =
136);" class=3D"styled-by-prettify">template</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"colo=
r: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">.=
...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
type_pack </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">;</span></div></code></div><p> </p><p>Usage example:=
</p><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);" class=3D"prettyprint"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0=
, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> my_types </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> type_pack</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&=
lt;</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettif=
y">int</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pr=
ettify">char</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled=
-by-prettify">double</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">>;</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);=
" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"> my_tuple </span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> tuple</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">my_types</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>;=
</span></div></code></div><p> </p><div><font size=3D"4"><strong>Variab=
le pack</strong></font></div><div> </div><p>Variable packs are the sam=
e as function parameter packs, except that they can be declared anywhere a =
variable can be declared. There are two ways to declare and initialize a va=
riable pack.</p><p>The first one is by using an already defined type pack. =
If constructor arguments are specified as single values, all the constructo=
rs of the variables in the pack are called with those same arguments.</p><d=
iv style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; ba=
ckground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 1=
36);" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"> types </span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> type_pack</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</sp=
an><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int<=
/span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify"=
>char</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pre=
ttify">double</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"><br>types values1</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"><br>type_pack</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span =
style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">char</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">double<=
/span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"=
>></span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> values2</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"><br>types values3 </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 102, =
102);" class=3D"styled-by-prettify">10</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(13=
6, 0, 0);" class=3D"styled-by-prettify">// all 3 variables are initialized =
to 10</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"><br>types values4</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 102, 102);" cl=
ass=3D"styled-by-prettify">10</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">);</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136, 0, 0)=
;" class=3D"styled-by-prettify">// same</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"><br>types values5 </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> values2</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>ty=
pe_pack</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-=
by-prettify">double</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D=
"styled-by-prettify">double</span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" =
class=3D"styled-by-prettify">double</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">></span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> values6 </span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> values2</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">//type_pack=
<int, char> values7 =3D values2; //error: mismatching pack sizes</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br=
></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify"=
>template</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled=
-by-prettify">class</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">></span><span style=3D"color: rgb(0, 0, 0);"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 13=
6);" class=3D"styled-by-prettify">class</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> C<br></span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"><br> T</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> values</span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">}=
;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><=
br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pre=
ttify">template</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"=
styled-by-prettify">class</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">></span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0=
, 136);" class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(=
0, 0, 0);" class=3D"styled-by-prettify"> f</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">)</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br> T</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t2 </=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> t </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-pr=
ettify">2</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify">}</span></div></code></div><div> </div><div> </di=
v><div>A variable pack can also be declared without a defined type pack. In=
that case, it must be initialized from another variable pack.</div><div>&n=
bsp;</div><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: br=
eak-word; background-color: rgb(250, 250, 250);" class=3D"prettyprint"><cod=
e class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color:=
rgb(136, 0, 0);" class=3D"styled-by-prettify">//double... values8; //error=
: unknown pack size</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D=
"styled-by-prettify">//double... values9 =3D 10.0; //error: unknown pack si=
ze</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pretti=
fy">double</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-b=
y-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"> values10 </span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> values2</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136, 0=
, 0);" class=3D"styled-by-prettify">// pack of 3 variables of type double</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">=
double</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"> values11</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify">values2</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">);</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136, 0, 0);" =
class=3D"styled-by-prettify">// same</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0=
, 136);" class=3D"styled-by-prettify">auto</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"> values12 </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> values2</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// pa=
ck of 3 variables of types int, char and double</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br><br><br></span><span s=
tyle=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">template</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">c=
lass</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">></span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"sty=
led-by-prettify">void</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> g</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify">T</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> t</span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">)</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">{</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"><br> </span><span style=3D"color: =
rgb(0, 0, 136);" class=3D"styled-by-prettify">auto</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t2 </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t </span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">*</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><=
span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">2</spa=
n><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">}</span></div></code></div><p><br>Operations can be done on packs if all =
the unexpanded packs are of the same size.</p><div style=3D"border: 1px sol=
id rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 25=
0, 250);" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify">values10 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"> values11 </span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify">*</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 102, 102)=
;" class=3D"styled-by-prettify">2.0</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"><br>values11 </span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">+=3D</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> values10</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>values=
11 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"> values10 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">+</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"> values11</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">;</span></div></code></div><p><br>Single values=
can be used along with pack but only in operations in which those single v=
alues are const.<code class=3D"prettyprint"></code></p><code class=3D"prett=
yprint"><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: brea=
k-word; background-color: rgb(250, 250, 250);" class=3D"subprettyprint"><sp=
an style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">double</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> singl=
e_value </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled=
-by-prettify">1.0</span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"><br>values10 </span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">*=3D</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify"> single_value</span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: rgb(136, 0, 0);" class=3D"styled-by-prettify">//ok: rhs is const single=
_value</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"><br>single_value </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">*=3D</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> values10</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136, =
0, 0);" class=3D"styled-by-prettify">//error: lhs of operator*=3D cannot be=
const</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-b=
y-prettify">void</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> h</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 136);" class=3D"s=
tyled-by-prettify">const</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" clas=
s=3D"styled-by-prettify">double</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">&,</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 0=
, 136);" class=3D"styled-by-prettify">double</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">&)</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">{}</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br>h</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">values10</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
values11</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by=
-prettify">//ok: 2 packs of the same size (h will be called 3 times)</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>h</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">sin=
gle_value</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"> values10</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D=
"styled-by-prettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=
=3D"styled-by-prettify">//ok: first arg of h is const (h will be called 3 t=
imes, each time with the same single_value)</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"><br>h</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify">values10</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> single_value</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">);=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/=
/error: trying to pass a non-const single value in an unexpanded context</s=
pan></div></code><p> </p><p><font size=3D"4"><strong>Variable template=
pack</strong></font></p><p>Variable packs should also work for variable te=
mplates.</p><p>The most basic (and useful) variable template packs would be=
an equivalent to std::integer_sequence that would allow working directly w=
ith an integer pack (instead of having to store that pack in a type).</p><d=
iv style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; ba=
ckground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 1=
36);" class=3D"styled-by-prettify">template</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color=
: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> I</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">const=
expr</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"> T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> integer_pack </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> I</span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, =
136);" class=3D"styled-by-prettify">template</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify">size_t</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span styl=
e=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> I</span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">constexpr=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> s=
ize_t</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> index_pack </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> I</span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, =
136);" class=3D"styled-by-prettify">template</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"colo=
r: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T N</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">constexp=
r</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"> make_integer_pack </span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> integer_pack</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: =
rgb(136, 0, 0);" class=3D"styled-by-prettify">/* a sequence 0, 1, 2, ..., N=
-1 */</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"st=
yled-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify">size_t N</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">></span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: r=
gb(0, 0, 136);" class=3D"styled-by-prettify">constexpr</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> size_t</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> make_index_p=
ack </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> make_integer_pack</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify">size_t</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"> N</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">>;</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span style=3D"co=
lor: rgb(0, 0, 136);" class=3D"styled-by-prettify">template</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><spa=
n style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T<=
/span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"=
>></span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pre=
ttify">constexpr</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> size_t</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> index_pack_for </span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"> make_index_pack</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><s=
pan style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">sizeof</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">.=
...(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
>T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">)>;</span></div></code></div><div> </div><p>With these variable=
template packs, additional utilies can be provided for tuple-like classes:=
</p><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);" class=3D"prettyprint"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(1=
36, 0, 0);" class=3D"styled-by-prettify">// tuple_indices<T> is equiv=
alenent to 0, 1, ..., tuple_size<T>::value - 1</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">template</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><=
span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&=
gt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prett=
ify">constexpr</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> size_t</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> tuple_indices </span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> make_index_pack</span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">tuple_size</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&=
lt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
>T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">>::</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify">value</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"><br><br></span><span style=3D"color: rgb(136, 0, 0);" cla=
ss=3D"styled-by-prettify">// tuple_elements<T> is equivalent to tuple=
_element_t<0, T>, tuple_element_t<1, T>, ..., tuple_element_t&l=
t;N-1, T></span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled=
-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 136);" c=
lass=3D"styled-by-prettify">class</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(102, 102,=
0);" class=3D"styled-by-prettify">></span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0=
, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> tuple_elements </span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> tuple_=
element_t</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify">tuple_indices</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);"=
class=3D"styled-by-prettify">T</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">>,</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">>;</span></div></code></div><p><=
br>These are much more simpler to use than current workarounds requiring us=
age of std::integer_sequence. Example of passing all elements of tuple t as=
arguments to a function f:</p><div style=3D"border: 1px solid rgb(187, 187=
, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">templat=
e</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pret=
tify">class</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> </span><span style=3D"color: rgb(102, 0, 102);" class=3D"sty=
led-by-prettify">Args</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">></span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);"=
class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> f</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(102, =
0, 102);" class=3D"styled-by-prettify">Args</span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify">&&...</span><span styl=
e=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> args</span><span s=
tyle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">);</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></sp=
an><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">temp=
late</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prett=
ify"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: rgb(102, 0, 102);" class=3D"style=
d-by-prettify">Tuple</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">></span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);"=
class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> g</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">&&</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t</span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br> f</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span=
><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">get</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&=
lt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
>tuple_indices</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify">T</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">>>(</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify">forward</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">>(</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify">t</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">))...);</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">}</span></div>=
</code></div><p> </p><p><strong><font size=3D"4">Returning a pack from=
a function</font></strong></p><p>With pack variables comes the need for fu=
nctions returning a pack of values.</p><p>The most basic function that coul=
d be defined is one returning a pack from several values:</p><div style=3D"=
border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-col=
or: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136);" class=
=3D"styled-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0);"=
class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0,=
136);" class=3D"styled-by-prettify">class</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">decltype</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">auto</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)=
....</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> make_pack</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify">T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">&&...</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> t</span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify">)</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">{</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136)=
;" class=3D"styled-by-prettify">return</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"> forward</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify">T</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">>(</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">t</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">);</span><span s=
tyle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">}</span></div=
></code></div><div> </div><div>Usage example:</div><div> </div><d=
iv style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; ba=
ckground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 1=
36);" class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> g</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(=
0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"> a</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color:=
rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> c</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> d</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> e</span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span=
><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> f</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
g</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pretti=
fy">int</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prett=
ify"> h</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"><br><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D"sty=
led-by-prettify">// Following functions forward all arguments to g by first=
multiplying them by 2 and adding 3</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0,=
136);" class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> f</span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rg=
b(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"> a</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> c</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span =
style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> d</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><=
span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> e</spa=
n><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">int=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> f=
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify=
">int</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> g</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pre=
ttify">int</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> h</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-b=
y-prettify">)</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"><br> </span><span style=3D"color: rgb(136, 0, 0);" cla=
ss=3D"styled-by-prettify">// Old way</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br> g</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify">a</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify">*</span><span style=3D"col=
or: rgb(0, 102, 102);" class=3D"styled-by-prettify">2</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">+</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">3</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span=
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">*</span><s=
pan style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">2</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">+</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">3</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
c</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">*</span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-pret=
tify">2</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">+</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-=
prettify">3</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> d</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify">*</span><span style=3D"color: rgb(0, 102, 102);" class=3D"s=
tyled-by-prettify">2</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">+</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> </span><span style=3D"color: rgb(0, 102, 102);" class=
=3D"styled-by-prettify">3</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> e</span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify">*</span><span style=3D"color: rgb(0, 102, 102=
);" class=3D"styled-by-prettify">2</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102,=
0);" class=3D"styled-by-prettify">+</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 102,=
102);" class=3D"styled-by-prettify">3</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> f</span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">*</span><span style=3D"color: rg=
b(0, 102, 102);" class=3D"styled-by-prettify">2</span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">+</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color=
: rgb(0, 102, 102);" class=3D"styled-by-prettify">3</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> g</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">*</span><span style=
=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">2</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">+</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">3</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> h</span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">*</spa=
n><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">2</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">+=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify"=
>3</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"><br> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled=
-by-prettify">// New way</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"><br> g</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify">make_pack</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify">a</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> c</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> d</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> e</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> f</span><span=
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> g</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> h</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)*</=
span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">=
2</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">+</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-pretti=
fy">3</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">...);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">}</span></div></code></div><br><p>Another usage would be a f=
unction returning all the values of a tuple-like class:</p><p><div style=3D=
"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-co=
lor: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint"=
><div class=3D"subprettyprint"><span style=3D"color: rgb(136, 0, 0);" class=
=3D"styled-by-prettify">// get_all(t) is equivalent to get<0>(t), get=
<1>(t), ..., get<N-1>(t)</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0=
, 136);" class=3D"styled-by-prettify">template</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">constexpr<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </=
span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">de=
cltype</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-p=
rettify">auto</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">)...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"> get_all</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify">T</span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">&&</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> t</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify">)</span><span style=3D"color: rgb(=
0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">{</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb=
(0, 0, 136);" class=3D"styled-by-prettify">return</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color=
: rgb(0, 0, 136);" class=3D"styled-by-prettify">get</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">tuple_indices</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
>>(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify">forward</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify">T</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">>(</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify">t</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">));</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">}</span></div></code></div><br>Usage example=
(passing all elements of tuple t as arguments to a function f):<p></p><div=
style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; back=
ground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136=
);" class=3D"styled-by-prettify">template</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: =
rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">void</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> f</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&a=
mp;&...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"> t</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D=
"styled-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 13=
6);" class=3D"styled-by-prettify">class</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102,=
0, 102);" class=3D"styled-by-prettify">Tuple</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: rgb(0, 0, 136);" class=3D"styled-by-prettify">void</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> g</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&&</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"><br> f</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify">get_all</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify">forward</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">>(</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify">t</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">))...);</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">}</span></div></code=
></div><p> </p><p><font size=3D"4"><strong>Expanding nested pack alias=
es</strong></font></p><p>Considering the following:</p><div style=3D"border=
: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rg=
b(250, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136);" class=3D"sty=
led-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> original </span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0,=
0, 0);" class=3D"styled-by-prettify"> type_pack</span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T0</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T1</span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span s=
tyle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/*...*/</span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> TN</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&g=
t;;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-p=
rettify">template</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 136);" class=
=3D"styled-by-prettify">class</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">></span><span style=3D"color: rgb(0,=
0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(=
0, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: rgb(0, 0, 136);" class=3D"styled-by-prettify">alias</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/*...*/</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><b=
r></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify=
">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"> a </span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" class=3D"sty=
led-by-prettify">alias</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify">original</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">...>;</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: =
rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b </span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span =
style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">alias</span><=
span style=3D"color: rgb(0, 136, 0);" class=3D"styled-by-prettify"><orig=
inal></span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify">...;</span></div></code></div><p><br>The pack a is the result of =
applying the alias on the entire original pack.<br>The pack b is the result=
of applying the alias on each individual elements of the original pack.</p=
><p><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);" class=3D"prettyprint"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0=
, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> a </span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">alias</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T0</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T1</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/=
*...*/</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> TN</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-b=
y-prettify">>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"s=
tyled-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" cla=
ss=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"> b </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"> type_pack</span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"colo=
r: rgb(0, 0, 136);" class=3D"styled-by-prettify">alias</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T0</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">>...,</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span=
><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">alias<=
/span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"=
><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y">T1</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">>...,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled=
-by-prettify">/*...*/</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> </span><span style=3D"color: rgb(0, 0, 136);" clas=
s=3D"styled-by-prettify">alias</span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify">TN</span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">>...>;</span></div></code></div=
><br>When multiple aliases are used, the same rules can be applied successi=
vely by considering the inner-most pack first.<br>The following example ill=
ustrates how the rules are applied when 2 aliases are used on a pack.<p></p=
><div style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word;=
background-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0,=
0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> orig </span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> type_pack</span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T0</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
T1</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-pretti=
fy">/*...*/</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> TN</span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" c=
lass=3D"styled-by-prettify">template</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0=
, 0, 136);" class=3D"styled-by-prettify">class</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">></span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> a1 </sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify=
">/*...*/</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"st=
yled-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 136);=
" class=3D"styled-by-prettify">class</span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> T</span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">></span><span style=3D"color:=
rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"colo=
r: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> a2 </span><span s=
tyle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/*...*/</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">;=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><b=
r><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pret=
tify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> a </span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> a1</span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify">a2</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify">orig</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">...>...>;</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// same as: using.=
... temp =3D a2<orig...>;</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(136, 0, 0)=
;" class=3D"styled-by-prettify">// using.=
... a =3D a1<temp...>;</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136=
);" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"> b </span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> a1</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">a2</span><span style=
=3D"color: rgb(0, 136, 0);" class=3D"styled-by-prettify"><orig></span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
....>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-=
prettify">// same as: using... temp =3D a2<orig>...;</span><span styl=
e=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">//  =
; using... b =3D a1<temp...>;</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span=
style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> c <=
/span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"> a1</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify">a2</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify">orig</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">...>>...;</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(136,=
0, 0);" class=3D"styled-by-prettify">// same as: using... temp =3D a2<o=
rig...>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-=
by-prettify">// using... c =3D a1<temp=
>...;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled=
-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> d </span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);"=
class=3D"styled-by-prettify"> a1</span><span style=3D"color: rgb(102, 102,=
0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify">a2</span><span style=3D"color: rgb(0, =
136, 0);" class=3D"styled-by-prettify"><orig></span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>...;</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// same a=
s: using... temp =3D a2<orig>...;</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(1=
36, 0, 0);" class=3D"styled-by-prettify">// &nb=
sp;using... d =3D a1<temp>...;</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(=
136, 0, 0);" class=3D"styled-by-prettify">//using... e =3D a1<a2<orig=
>>... ...;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D"st=
yled-by-prettify">// error</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(136, 0, 0)=
;" class=3D"styled-by-prettify">//using... f =3D a1<a2<orig... ...>=
;>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-pr=
ettify">// error</span></div></code></div><p><br>Additional examples</p><di=
v style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; bac=
kground-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"pr=
ettyprint"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 13=
6);" class=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0,=
0, 0);" class=3D"styled-by-prettify"> A </span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">{};</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: rgb(0, 0, 136);" class=3D"styled-by-prettify">struct</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> B </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{};</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span>=
<span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">templat=
e</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
"><</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pret=
tify">class</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> T</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">></span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=
=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> twice </span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> type_pack</span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span styl=
e=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">T</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...,</span><span=
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</span><span=
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>;</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
<br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pretti=
fy">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> AB </span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> type_pack</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify">A</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify"> B</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">>;</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> &nbs=
p; </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-=
prettify">// A, B</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"s=
tyled-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" cla=
ss=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"> t1 </span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"> twice</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">...>;</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">  =
; </span><span style=3D"color: rgb(136, 0=
, 0);" class=3D"styled-by-prettify">// A, B, A, B</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t2 </span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> type_pa=
ck</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify">twice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify">...>...>;</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136=
, 0, 0);" class=3D"styled-by-prettify">// A, B, A, B</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t3 </span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> twice=
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy">AB</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">>...;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> </spa=
n><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A,=
A, B, B</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-=
prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"> t4 </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> type_pack</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify">twice</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">>...</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>;</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><=
span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A, A,=
B, B</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pre=
ttify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"> t5 </span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> twice</span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify">twice</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">...>...>;</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-pret=
tify">// A, B, A, B, A, B, A, B</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136=
);" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"> t6 </span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> twice</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">twice</span><span=
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">>=
....</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">...>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"> </span><span style=3D"color: rgb(136, 0, 0);" clas=
s=3D"styled-by-prettify">// A, A, B, B, A, A, B, B</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> t7 </span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> twice</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
<</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
">twice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">...>>...;</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> </span><span style=3D"colo=
r: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A, A, B, B, A, A, B, B<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify"=
>using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"> t8 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"> twice</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify">twice</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0,=
0);" class=3D"styled-by-prettify">AB</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">>...>...;</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </=
span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">//=
A, A, A, A, B, B, B, B</span><span style=3D"color: rgb(0, 0, 0);" class=3D=
"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" =
class=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"> C </span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">{};</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span style=3D"color:=
rgb(0, 0, 136);" class=3D"styled-by-prettify">template</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span=
style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">class</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> T</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
></span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pret=
tify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> add_c </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> type_pack</span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify">T</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">...,</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"> C</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">>;</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span sty=
le=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> u1 </sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> add_c</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">...>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D=
"styled-by-prettify"> </span><span=
style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A, B, C</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">=
using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> u2 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"> add_c</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify">>...;</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"> &nb=
sp;</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettif=
y">// A, C, B, C</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"st=
yled-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> u3 </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"> add_c</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify">add_c</span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>...>;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">  =
;</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify"=
>// A, B, C, C</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styl=
ed-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> u4 </span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> add_c</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify">add_c</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">>...</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A,=
C, B, C, C</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-=
by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D=
"styled-by-prettify"> u5 </span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> add_c</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0,=
0, 0);" class=3D"styled-by-prettify">add_c</span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>>...;</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A=
, C, B, C, C, C</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"sty=
led-by-prettify">using</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"> u6 </span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> add_c</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify">add_c</span><span style=3D"color:=
rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">>...>...;</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">=
// A, C, C, C, B, C, C, C</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136)=
;" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb(=
0, 0, 0);" class=3D"styled-by-prettify"> v1 </span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> add_c</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">twice</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...&g=
t;...>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"style=
d-by-prettify">// A, B, A, B, C</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136=
);" class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102,=
102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"> v2 </span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> add_c</span><span style=3D=
"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">twice</span><span=
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">>=
....</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">...>;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by=
-prettify">// A, A, B, B, C</span><span style=3D"color: rgb(0, 0, 0);" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0, 0, 136);" =
class=3D"styled-by-prettify">using</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">...</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> v3 </span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"> add_c</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">twice</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">AB</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...>=
>...;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-=
by-prettify">// A, C, B, C, A, C, B, C</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(0,=
0, 136);" class=3D"styled-by-prettify">using</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> v4 </span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> add_c</span><span s=
tyle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">twice</spa=
n><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify"><=
;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">A=
B</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">>...>...;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: rgb(136, 0, 0);" class=
=3D"styled-by-prettify">// A, C, A, C, B, C, B, C</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> w1 </span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=3D<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> tw=
ice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prett=
ify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify">add_c</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">...>...>;</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(13=
6, 0, 0);" class=3D"styled-by-prettify">// A, B, C, A, B, C</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">...</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> w2 </=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> twice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify">add_c</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">>...</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">...>;</span><span style=3D"color: rgb(0,=
0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(136=
, 0, 0);" class=3D"styled-by-prettify">// A, C, B, C, A, C, B, C</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">..=
..</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
w3 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pret=
tify"> twice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify">add_c</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify">AB</span><span style=3D"color: rgb(102, 102, 0);"=
class=3D"styled-by-prettify">...>>...;</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A, A, B, B, C, C</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">usin=
g</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"> w4 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"> twice</span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);" class=3D=
"styled-by-prettify">add_c</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify"><</span><span style=3D"color: rgb(0, 0, 0);"=
class=3D"styled-by-prettify">AB</span><span style=3D"color: rgb(102, 102, =
0);" class=3D"styled-by-prettify">>...>...;</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D=
"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">// A, A, C, C, B, B, =
C, C</span></div></code></div><p> </p></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_870_24339805.1385149007894--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Fri, 22 Nov 2013 12:33:32 -0800
Raw View
--047d7bdc051e89cf9f04ebc9ed3a
Content-Type: text/plain; charset=ISO-8859-1
On Fri, Nov 22, 2013 at 11:36 AM, Alex B <devalexb@gmail.com> wrote:
> Hi,
>
> I have been working on several ideas that would fill several gaps and make
> things much easier when dealing with parameter packs. Before going in with
> a formal proposal, I first wanted to share my ideas. Feedback would be
> greatly appreciated.
>
> *Type pack alias*
>
> A pack alias (templated or not) can be defined with a "using..."
> directive. On the right hand side must be an unexpanded type pack. This
> unexpanded type pack can come from an unexpanded parameter pack of a
> variadic template or from another pack alias.
>
>
> A pack alias can be expanded with the "..." operator in the same way as an
> unexanded parameter pack of a variadic template.
>
> The most basic (and useful) templated pack alias would be the following,
> which allow creating packs on the fly:
> template <class... T>
> using... type_pack = T;
>
>
>
> Usage example:
> using... my_types = type_pack<int, char, double>;
> using my_tuple = tuple<my_types...>;
>
>
This immediately creates a problem. One of the properties of packs today is
that it is possible to syntactically determine whether some snippet of C++
syntax contains unexpanded parameter packs, and to determine which packs it
contains. This is crucial to some implementation techniques.
It's also important in resolving some grammar ambiguities. Today, if I have:
template<typename T> void f(typename T::type x ...);
I know this is a vararg function. With your proposal, I could presumably
write:
template<typename...Ts> struct X {
using ...type = Ts;
};
void g() {
f<X<int, int, int>>(1, 2, 3);
}
and 'f' would mean something fundamentally different.
I had a similar-but-different proposal a while back (which I've not written
up for committee consideration yet) which avoids this problem by using a
slightly different syntax:
template<typename...Ts> struct types {
using ... = Ts; // "...types<Ts>" is the pack "Ts"
};
typedef std::types<int, char, double> icd; // just a normal type
void f(...icd ...x) // "...icd" is a pack of types; this is "void f(int,
char, double)" except that we have a pack of parameters
*Variable pack*
>
>
> Variable packs are the same as function parameter packs, except that they
> can be declared anywhere a variable can be declared. There are two ways to
> declare and initialize a variable pack.
>
> The first one is by using an already defined type pack. If constructor
> arguments are specified as single values, all the constructors of the
> variables in the pack are called with those same arguments.
> using... types = type_pack<int, char, double>;
> types values1;
>
This syntax doesn't work. Consider:
template<typename ...Ts>
void f(Ts ...ts) {
g(ts + []() {
types values;
return values;
}() ...);
}
This would be ambiguous: does each lambda declare a *pack* of values, or a
*slice* of that pack of values? The way to fix this is to consistently use
pack expansion whenever you expand a pack:
// assuming 'types' names a pack of types
types ...values1; // ok, declare a pack of values named 'values1'.
This would still be problematic if you allowed pack expansions as a static
or non-static data member, because of the above-mentioned problem with
being unable to syntactically determine what is and is not a pack.
> type_pack<int, char, double> values2;
> types values3 = 10; // all 3 variables are initialized to 10
> types values4(10); // same
> types values5 = values2;
> type_pack<double, double, double> values6 = values2;
> //type_pack<int, char> values7 = values2; //error: mismatching pack sizes
>
> template <class... T>
> class C
> {
> T... values;
>
This, for instance, is a problem, because X::values (for a dependent type
X) might or might not be a pack if this were valid.
>
> };
>
> template <class... T>
> void f(T... t)
> {
> T... t2 = t * 2;
> }
>
>
> A variable pack can also be declared without a defined type pack. In that
> case, it must be initialized from another variable pack.
>
> //double... values8; //error: unknown pack size
> //double... values9 = 10.0; //error: unknown pack size
> double... values10 = values2; // pack of 3 variables of type double
> double... values11(values2); // same
>
Seems fine to me: the pack expansion includes 'values2', so can infer its
length from there.
>
> auto... values12 = values2; // pack of 3 variables of types int, char and
> double
>
Presumably this means that your expansion model is that this expands to
auto values12$0 = values2$0;
auto values12$1 = values2$1;
auto vaules12$2 = values2$2;
not the more natural choice of
auto values12$0 = values2$0, values12$1 = values2$1, vaules12$2 =
values2$2;
(which would be ill-formed, because the 'auto' deduces to different types
in different deductions).
>
>
>
> template <class... T>
> void g(T... t)
> {
> auto... t2 = t * 2;
> }
>
>
> Operations can be done on packs if all the unexpanded packs are of the
> same size.
> values10 = values11 * 2.0;
> values11 += values10;
> values11 = values10 + values11;
>
Again, this doesn't work, due to ambiguity over where the expansion
happens. Instead, I'd suggest (and indeed, have been intending to propose
for standardization) adding an optional '...' before the ';' in an
expression-statement, to represent a pack expansion. So you'd write:
values10 = values11 * 2.0 ...;
and it would be equivalent to today's
sink{ values10 = values11 * 2.0 ... };
(for an appropriately-defined class 'sink')
> Single values can be used along with pack but only in operations in which
> those single values are const.
> double single_value = 1.0;
> values10 *= single_value; //ok: rhs is const single_value
> single_value *= values10; //error: lhs of operator*= cannot be const
>
> void h(const double&, double&) {}
>
> h(values10, values11); //ok: 2 packs of the same size (h will be called 3
> times)
> h(single_value, values10); //ok: first arg of h is const (h will be
> called 3 times, each time with the same single_value)
> h(values10, single_value); //error: trying to pass a non-const single
> value in an unexpanded context
>
>
>
> *Variable template pack*
>
> Variable packs should also work for variable templates.
>
> The most basic (and useful) variable template packs would be an equivalent
> to std::integer_sequence that would allow working directly with an integer
> pack (instead of having to store that pack in a type).
> template <class T, T... I>
> constexpr T... integer_pack = I;
>
> template <size_t... I>
> constexpr size_t... index_pack = I;
>
> template <class T, T N>
> constexpr T... make_integer_pack = integer_pack<T, /* a sequence 0, 1, 2,
> ..., N-1 */>;
>
My prior proposal had syntax for this sequence: ...N. This was also
overloadable for user-defined types, so that (for instance) for a tuple t,
'...t' could be sugar for 'get<...N>(t)'.
> template <size_t N>
> constexpr size_t... make_index_pack = make_integer_pack<size_t, N>;
>
> template <class... T>
> constexpr size_t... index_pack_for = make_index_pack<sizeof...(T)>;
>
>
> With these variable template packs, additional utilies can be provided for
> tuple-like classes:
> // tuple_indices<T> is equivalenent to 0, 1, ..., tuple_size<T>::value - 1
> template <class T>
> constexpr size_t... tuple_indices = make_index_pack<tuple_size<T>::value>;
>
> // tuple_elements<T> is equivalent to tuple_element_t<0, T>,
> tuple_element_t<1, T>, ..., tuple_element_t<N-1, T>
> template <class T>
> using... tuple_elements = tuple_element_t<tuple_indices<T>, T>;
>
>
> These are much more simpler to use than current workarounds requiring
> usage of std::integer_sequence. Example of passing all elements of tuple t
> as arguments to a function f:
> template <class... Args>
> void f(Args&&... args);
>
> template <class Tuple>
> void g(T&& t)
> {
> f(get<tuple_indices<T>>(forward<T>(t))...);
> }
>
This is still a little unclean. My proposal supports this as:
f(...std::forward<T>(t) ...);
> *Returning a pack from a function*
>
> With pack variables comes the need for functions returning a pack of
> values.
>
Why not return a tuple? Packs are not types, so functions returning packs
doesn't really seem to make much sense.
> The most basic function that could be defined is one returning a pack from
> several values:
> template <class... T>
> decltype(auto)... make_pack(T&&... t) { return forward<T>(t); }
>
> Usage example:
>
> void g(int a, int b, int c, int d, int e, int f, int g, int h);
>
> // Following functions forward all arguments to g by first multiplying
> them by 2 and adding 3
> void f(int a, int b, int c, int d, int e, int f, int g, int h)
> {
> // Old way
> g(a*2 + 3, b*2 + 3, c*2 + 3, d*2 + 3, e*2 + 3, f*2 + 3, g*2 + 3, h*2 + 3
> );
> // New way
> g(make_pack(a, b, c, d, e, f, g, h)*2 + 3 ...);
>
Again, this has the problem of not syntactically identifying what's a pack
and what's not. With my syntax:
g(...tie(a, b, c, d, e, f, g, h)*2 + 3...);
> }
>
> Another usage would be a function returning all the values of a tuple-like
> class:
>
> // get_all(t) is equivalent to get<0>(t), get<1>(t), ..., get<N-1>(t)
> template <class T>
> constexpr decltype(auto)... get_all(T&& t) { return get<tuple_indices<T>>(
> forward<T>(t)); }
>
> Usage example (passing all elements of tuple t as arguments to a function
> f):
>
> template <class... T>
> void f(T&&... t);
>
> template <class Tuple>
> void g(T&& t)
> {
> f(get_all(forward<T>(t))...);
> }
>
>
>
> *Expanding nested pack aliases*
>
> Considering the following:
> using... original = type_pack<T0, T1, /*...*/, TN>;
>
> template <class... T>
> using... alias = /*...*/;
>
> using... a = alias<original...>;
> using... b = alias<original>...;
>
>
> The pack a is the result of applying the alias on the entire original pack.
> The pack b is the result of applying the alias on each individual elements
> of the original pack.
>
> using... a = alias<T0, T1, /*...*/, TN>;
> using... b = type_pack<alias<T0>..., alias<T1>..., /*...*/, alias<TN>...>;
>
> When multiple aliases are used, the same rules can be applied successively
> by considering the inner-most pack first.
> The following example illustrates how the rules are applied when 2 aliases
> are used on a pack.
>
> using... orig = type_pack<T0, T1, /*...*/, TN>;
>
> template <class... T>
> using... a1 = /*...*/;
>
> template <class... T>
> using... a2 = /*...*/;
>
> using... a = a1<a2<orig...>...>;
> // same as: using... temp = a2<orig...>;
> // using... a = a1<temp...>;
>
> using... b = a1<a2<orig>... ...>;
> // same as: using... temp = a2<orig>...;
> // using... b = a1<temp...>;
>
> using... c = a1<a2<orig...>>...;
> // same as: using... temp = a2<orig...>;
> // using... c = a1<temp>...;
>
> using... d = a1<a2<orig>...>...;
> // same as: using... temp = a2<orig>...;
> // using... d = a1<temp>...;
>
> //using... e = a1<a2<orig>>... ...;
> // error
>
> //using... f = a1<a2<orig... ...>>;
> // error
>
>
> Additional examples
> struct A {};
> struct B {};
>
> template <class... T>
> using... twice = type_pack<T..., T...>;
>
> using... AB = type_pack<A, B>; // A, B
> using... t1 = twice<AB...>; // A, B, A, B
> using... t2 = type_pack<twice<AB...>...>; // A, B, A, B
> using... t3 = twice<AB>...; // A, A, B, B
> using... t4 = type_pack<twice<AB>... ...>; // A, A, B, B
> using... t5 = twice<twice<AB...>...>; // A, B, A, B, A, B, A, B
> using... t6 = twice<twice<AB>... ...>; // A, A, B, B, A, A, B, B
> using... t7 = twice<twice<AB...>>...; // A, A, B, B, A, A, B, B
> using... t8 = twice<twice<AB>...>...; // A, A, A, A, B, B, B, B
>
> struct C {};
>
> template <class... T>
> using... add_c = type_pack<T..., C>;
>
> using... u1 = add_c<AB...>; // A, B, C
> using... u2 = add_c<AB>...; // A, C, B, C
> using... u3 = add_c<add_c<AB...>...>; // A, B, C, C
> using... u4 = add_c<add_c<AB>... ...>; // A, C, B, C, C
> using... u5 = add_c<add_c<AB...>>...; // A, C, B, C, C, C
> using... u6 = add_c<add_c<AB>...>...; // A, C, C, C, B, C, C, C
>
> using... v1 = add_c<twice<AB...>...>; // A, B, A, B, C
> using... v2 = add_c<twice<AB>... ...>; // A, A, B, B, C
> using... v3 = add_c<twice<AB...>>...; // A, C, B, C, A, C, B, C
> using... v4 = add_c<twice<AB>...>...; // A, C, A, C, B, C, B, C
>
> using... w1 = twice<add_c<AB...>...>; // A, B, C, A, B, C
> using... w2 = twice<add_c<AB>... ...>; // A, C, B, C, A, C, B, C
> using... w3 = twice<add_c<AB...>>...; // A, A, B, B, C, C
> using... w4 = twice<add_c<AB>...>...; // A, A, C, C, B, B, C, C
>
>
>
> --
>
> ---
> 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/.
>
>
--
---
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/.
--047d7bdc051e89cf9f04ebc9ed3a
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Nov 22, 2013 at 11:36 AM, Alex B <span dir=3D"ltr"=
><<a href=3D"mailto:devalexb@gmail.com" target=3D"_blank">devalexb@gmail=
..com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>Hi,</div><div>=A0</div><div>I have b=
een working on several ideas=A0that would fill several gaps and make things=
much easier when dealing with parameter packs. Before going in with a form=
al proposal, I first wanted to share my ideas. Feedback would be greatly ap=
preciated.</div>
<div><strong><font size=3D"4"></font></strong>=A0</div><div><font size=3D"4=
"><strong>Type pack alias</strong></font></div><div>=A0</div><div>A pack al=
ias (templated or not) can be defined with a "using..." directive=
.. On the right hand side must be an unexpanded type pack. This unexpanded t=
ype pack can come from an unexpanded parameter pack of a variadic template =
or from another pack alias.</div>
<div>=A0</div><p>A pack alias can be expanded with the "..." oper=
ator in the same way as an unexanded parameter pack of a variadic template.=
</p><p>The most basic (and useful) templated pack alias would be the follow=
ing, which allow creating packs on the fly:</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span style> </span><span style=3D"color:rgb(102,102,0)"><=
;</span><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color=
:rgb(102,102,0)">...</span><span style> T</span><span style=3D"color:rgb(10=
2,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> type_pack </span><span style=3D"colo=
r:rgb(102,102,0)">=3D</span><span style> T</span><span style=3D"color:rgb(1=
02,102,0)">;</span></div>
</code></div><p>=A0</p><p>Usage example:</p><div style=3D"border:1px solid =
rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><c=
ode><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"colo=
r:rgb(102,102,0)">...</span><span style> my_types </span><span style=3D"col=
or:rgb(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"co=
lor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span=
><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><span sty=
le=3D"color:rgb(0,0,136)">char</span><span style=3D"color:rgb(102,102,0)">,=
</span><span style> </span><span style=3D"color:rgb(0,0,136)">double</span>=
<span style=3D"color:rgb(102,102,0)">>;</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style> my_tuple=
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> tuple</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style>my_types</=
span><span style=3D"color:rgb(102,102,0)">...>;</span></div>
</code></div><p></p></div></blockquote><div><br></div><div>This immediately=
creates a problem. One of the properties of packs today is that it is poss=
ible to syntactically determine whether some snippet of C++ syntax contains=
unexpanded parameter packs, and to determine which packs it contains. This=
is crucial to some implementation techniques.</div>
<div><br></div><div>It's also important in resolving some grammar ambig=
uities. Today, if I have:</div><div><br></div><div>=A0 template<typename=
T> void f(typename T::type x ...);<br></div><div><br></div><div>I know =
this is a vararg function. With your proposal, I could presumably write:</d=
iv>
<div><br></div><div>=A0 template<typename...Ts> struct X {</div><div>=
=A0 =A0 using ...type =3D Ts;</div><div>=A0 };</div><div>=A0 void g() {</di=
v><div>=A0 =A0 f<X<int, int, int>>(1, 2, 3);</div><div>=A0 }</d=
iv><div><br></div>
<div>and 'f' would mean something fundamentally different.</div><di=
v><br></div><div>I had a similar-but-different proposal a while back (which=
I've not written up for committee consideration yet) which avoids this=
problem by using a slightly different syntax:</div>
<div><br></div><div>=A0 template<typename...Ts> struct types {</div><=
div>=A0 =A0 using ... =3D Ts; // "...types<Ts>" is the pack=
"Ts"</div><div>=A0 };</div><div><br></div><div>=A0 typedef std::=
types<int, char, double> icd; // just a normal type</div>
<div>=A0 void f(...icd ...x) // "...icd" is a pack of types; this=
is "void f(int, char, double)" except that we have a pack of par=
ameters</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div><font size=3D"4"><strong>Variable pack</strong></font=
></div><div>=A0</div><p>Variable packs are the same as function parameter p=
acks, except that they can be declared anywhere a variable can be declared.=
There are two ways to declare and initialize a variable pack.</p>
<p>The first one is by using an already defined type pack. If constructor a=
rguments are specified as single values, all the constructors of the variab=
les in the pack are called with those same arguments.</p><div style=3D"bord=
er:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250=
,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> types </span><span style=3D"colo=
r:rgb(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"col=
or:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span>=
<span style=3D"color:rgb(102,102,0)">,</span><span style> </span><span styl=
e=3D"color:rgb(0,0,136)">char</span><span style=3D"color:rgb(102,102,0)">,<=
/span><span style> </span><span style=3D"color:rgb(0,0,136)">double</span><=
span style=3D"color:rgb(102,102,0)">>;</span><span style><br>
types values1</span><span style=3D"color:rgb(102,102,0)">;</span></div></co=
de></div></div></blockquote><div><br></div><div>This syntax doesn't wor=
k. Consider:</div><div><br></div><div>=A0 template<typename ...Ts></d=
iv>
<div>=A0 void f(Ts ...ts) {</div><div>=A0 =A0 g(ts + []() {</div><div>=A0 =
=A0 =A0 types values;</div><div>=A0 =A0 =A0 return values;</div><div>=A0 =
=A0 }() ...);</div><div>=A0 }</div><div><br></div><div>This would be ambigu=
ous: does each lambda declare a *pack* of values, or a *slice* of that pack=
of values? The way to fix this is to consistently use pack expansion whene=
ver you expand a pack:</div>
<div><br></div><div>=A0 // assuming 'types' names a pack of types</=
div><div>=A0 types ...values1; // ok, declare a pack of values named 'v=
alues1'.</div><div><br></div><div>This would still be problematic if yo=
u allowed pack expansions as a static or non-static data member, because of=
the above-mentioned problem with being unable to syntactically determine w=
hat is and is not a pack.</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px s=
olid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250=
)">
<code><div><span style><br>type_pack</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D=
"color:rgb(102,102,0)">,</span><span style> </span><span style=3D"color:rgb=
(0,0,136)">char</span><span style=3D"color:rgb(102,102,0)">,</span><span st=
yle> </span><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"=
color:rgb(102,102,0)">></span><span style> values2</span><span style=3D"=
color:rgb(102,102,0)">;</span><span style><br>
types values3 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span s=
tyle> </span><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"c=
olor:rgb(102,102,0)">;</span><span style> </span><span style=3D"color:rgb(1=
36,0,0)">// all 3 variables are initialized to 10</span><span style><br>
types values4</span><span style=3D"color:rgb(102,102,0)">(</span><span styl=
e=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">);=
</span><span style> </span><span style=3D"color:rgb(136,0,0)">// same</span=
><span style><br>
types values5 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span s=
tyle> values2</span><span style=3D"color:rgb(102,102,0)">;</span><span styl=
e><br>type_pack</span><span style=3D"color:rgb(102,102,0)"><</span><span=
style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,102=
,0)">,</span><span style> </span><span style=3D"color:rgb(0,0,136)">double<=
/span><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><spa=
n style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,10=
2,0)">></span><span style> values6 </span><span style=3D"color:rgb(102,1=
02,0)">=3D</span><span style> values2</span><span style=3D"color:rgb(102,10=
2,0)">;</span><span style><br>
</span><span style=3D"color:rgb(136,0,0)">//type_pack<int, char> valu=
es7 =3D values2; //error: mismatching pack sizes</span><span style><br><br>=
</span><span style=3D"color:rgb(0,0,136)">template</span><span style> </spa=
n><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(=
0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span =
style> T</span><span style=3D"color:rgb(102,102,0)">></span><span style>=
<br>
</span><span style=3D"color:rgb(0,0,136)">class</span><span style> C<br></s=
pan><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0T</span=
><span style=3D"color:rgb(102,102,0)">...</span><span style> values</span><=
span style=3D"color:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div><div>This, for instance, is =
a problem, because X::values (for a dependent type X) might or might not be=
a pack if this were valid.</div><div>=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style><br></=
span><span style=3D"color:rgb(102,102,0)">};</span><span style><br><br></sp=
an><span style=3D"color:rgb(0,0,136)">template</span><span style> </span><s=
pan style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,=
136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span styl=
e> T</span><span style=3D"color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">...</span><span style> t</span><span style=3D"col=
or:rgb(102,102,0)">)</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0T</s=
pan><span style=3D"color:rgb(102,102,0)">...</span><span style> t2 </span><=
span style=3D"color:rgb(102,102,0)">=3D</span><span style> t </span><span s=
tyle=3D"color:rgb(102,102,0)">*</span><span style> </span><span style=3D"co=
lor:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)">;</span><s=
pan style><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><div=
>=A0</div><div>=A0</div><div>A variable pack can also be declared without a=
defined type pack. In that case, it must be initialized from another varia=
ble pack.</div>
<div>=A0</div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:bre=
ak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"color:=
rgb(136,0,0)">//double... values8; //error: unknown pack size</span><span s=
tyle><br>
</span><span style=3D"color:rgb(136,0,0)">//double... values9 =3D 10.0; //e=
rror: unknown pack size</span><span style><br></span><span style=3D"color:r=
gb(0,0,136)">double</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> values10 </span><span style=3D"color:rgb(102,102,0)">=3D</span><=
span style> values2</span><span style=3D"color:rgb(102,102,0)">;</span><spa=
n style> </span><span style=3D"color:rgb(136,0,0)">// pack of 3 variables o=
f type double</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color=
:rgb(102,102,0)">...</span><span style> values11</span><span style=3D"color=
:rgb(102,102,0)">(</span><span style>values2</span><span style=3D"color:rgb=
(102,102,0)">);</span><span style> </span><span style=3D"color:rgb(136,0,0)=
">// same</span></div>
</code></div></div></blockquote><div><br></div><div>Seems fine to me: the p=
ack expansion includes 'values2', so can infer its length from ther=
e.</div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style><br></=
span><span style=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb=
(102,102,0)">...</span><span style> values12 </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> values2</span><span style=3D"color:rgb=
(102,102,0)">;</span><span style> </span><span style=3D"color:rgb(136,0,0)"=
>// pack of 3 variables of types int, char and double</span></div>
</code></div></div></blockquote><div><br></div><div>Presumably this means t=
hat your expansion model is that this expands to</div><div><br></div><div><=
div>=A0 auto values12$0 =3D values2$0;</div><div>=A0 auto values12$1 =3D va=
lues2$1;</div>
<div>=A0 auto vaules12$2 =3D values2$2;</div></div><div><br></div><div>not =
the more natural choice of</div><div><br></div><div>=A0 auto values12$0 =3D=
values2$0, values12$1 =3D values2$1, vaules12$2 =3D values2$2;</div><div><=
br></div>
<div>(which would be ill-formed, because the 'auto' deduces to diff=
erent types in different deductions).</div><div>=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style><br><b=
r><br></span><span style=3D"color:rgb(0,0,136)">template</span><span style>=
</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"colo=
r:rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span>=
<span style> T</span><span style=3D"color:rgb(102,102,0)">></span><span =
style><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> g</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">...</span><span style> t</span><span style=3D"col=
or:rgb(102,102,0)">)</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0</sp=
an><span style=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(1=
02,102,0)">...</span><span style> t2 </span><span style=3D"color:rgb(102,10=
2,0)">=3D</span><span style> t </span><span style=3D"color:rgb(102,102,0)">=
*</span><span style> </span><span style=3D"color:rgb(0,102,102)">2</span><s=
pan style=3D"color:rgb(102,102,0)">;</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><p><=
br>Operations can be done on packs if all the unexpanded packs are of the s=
ame size.</p><div style=3D"border:1px solid rgb(187,187,187);word-wrap:brea=
k-word;background-color:rgb(250,250,250)">
<code><div><span style>values10 </span><span style=3D"color:rgb(102,102,0)"=
>=3D</span><span style> values11 </span><span style=3D"color:rgb(102,102,0)=
">*</span><span style> </span><span style=3D"color:rgb(0,102,102)">2.0</spa=
n><span style=3D"color:rgb(102,102,0)">;</span><span style><br>
values11 </span><span style=3D"color:rgb(102,102,0)">+=3D</span><span style=
> values10</span><span style=3D"color:rgb(102,102,0)">;</span><span style><=
br>values11 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span sty=
le> values10 </span><span style=3D"color:rgb(102,102,0)">+</span><span styl=
e> values11</span><span style=3D"color:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div><div>Again, this doesn't=
work, due to ambiguity over where the expansion happens. Instead, I'd =
suggest (and indeed, have been intending to propose for standardization) ad=
ding an optional '...' before the ';' in an expression-stat=
ement, to represent a pack expansion. So you'd write:</div>
<div><br></div><div>=A0 values10 =3D values11 * 2.0 ...;</div><div><br></di=
v><div>and it would be equivalent to today's</div><div><br></div><div>=
=A0 sink{ values10 =3D values11 * 2.0 ... };</div><div>=A0</div><div>(for a=
n appropriately-defined class 'sink')</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p>Single values can be used along with p=
ack but only in operations in which those single values are const.<code></c=
ode></p>
<code><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><span style=3D"color:rgb(0,0,136)">doubl=
e</span><span style> single_value </span><span style=3D"color:rgb(102,102,0=
)">=3D</span><span style> </span><span style=3D"color:rgb(0,102,102)">1.0</=
span><span style=3D"color:rgb(102,102,0)">;</span><span style><br>
values10 </span><span style=3D"color:rgb(102,102,0)">*=3D</span><span style=
> single_value</span><span style=3D"color:rgb(102,102,0)">;</span><span sty=
le> </span><span style=3D"color:rgb(136,0,0)">//ok: rhs is const single_val=
ue</span><span style><br>
single_value </span><span style=3D"color:rgb(102,102,0)">*=3D</span><span s=
tyle> values10</span><span style=3D"color:rgb(102,102,0)">;</span><span sty=
le> </span><span style=3D"color:rgb(136,0,0)">//error: lhs of operator*=3D =
cannot be const</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">void</span><span style> h</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,=
0,136)">const</span><span style> </span><span style=3D"color:rgb(0,0,136)">=
double</span><span style=3D"color:rgb(102,102,0)">&,</span><span style>=
</span><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"colo=
r:rgb(102,102,0)">&)</span><span style> </span><span style=3D"color:rgb=
(102,102,0)">{}</span><span style><br>
<br>h</span><span style=3D"color:rgb(102,102,0)">(</span><span style>values=
10</span><span style=3D"color:rgb(102,102,0)">,</span><span style> values11=
</span><span style=3D"color:rgb(102,102,0)">);</span><span style> </span><s=
pan style=3D"color:rgb(136,0,0)">//ok: 2 packs of the same size (h will be =
called 3 times)</span><span style><br>
h</span><span style=3D"color:rgb(102,102,0)">(</span><span style>single_val=
ue</span><span style=3D"color:rgb(102,102,0)">,</span><span style> values10=
</span><span style=3D"color:rgb(102,102,0)">);</span><span style> </span><s=
pan style=3D"color:rgb(136,0,0)">//ok: first arg of h is const (h will be c=
alled 3 times, each time with the same single_value)</span><span style><br>
h</span><span style=3D"color:rgb(102,102,0)">(</span><span style>values10</=
span><span style=3D"color:rgb(102,102,0)">,</span><span style> single_value=
</span><span style=3D"color:rgb(102,102,0)">);</span><span style> </span><s=
pan style=3D"color:rgb(136,0,0)">//error: trying to pass a non-const single=
value in an unexpanded context</span></div>
</code><p>=A0</p><p><font size=3D"4"><strong>Variable template pack</strong=
></font></p><p>Variable packs should also work for variable templates.</p><=
p>The most basic (and useful) variable template packs would be an equivalen=
t to std::integer_sequence that would allow working directly with an intege=
r pack (instead of having to store that pack in a type).</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span style> </span><span style=3D"color:rgb(102,102,0)"><=
;</span><span style=3D"color:rgb(0,0,136)">class</span><span style> T</span=
><span style=3D"color:rgb(102,102,0)">,</span><span style> T</span><span st=
yle=3D"color:rgb(102,102,0)">...</span><span style> I</span><span style=3D"=
color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> T</s=
pan><span style=3D"color:rgb(102,102,0)">...</span><span style> integer_pac=
k </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> I</spa=
n><span style=3D"color:rgb(102,102,0)">;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style>size_t</s=
pan><span style=3D"color:rgb(102,102,0)">...</span><span style> I</span><sp=
an style=3D"color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> size=
_t</span><span style=3D"color:rgb(102,102,0)">...</span><span style> index_=
pack </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> I</=
span><span style=3D"color:rgb(102,102,0)">;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style> T</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style> T N</span><span style=3D"color:rgb(102,102,0)=
">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> T</s=
pan><span style=3D"color:rgb(102,102,0)">...</span><span style> make_intege=
r_pack </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> i=
nteger_pack</span><span style=3D"color:rgb(102,102,0)"><</span><span sty=
le>T</span><span style=3D"color:rgb(102,102,0)">,</span><span style> </span=
><span style=3D"color:rgb(136,0,0)">/* a sequence 0, 1, 2, ..., N-1 */</spa=
n><span style=3D"color:rgb(102,102,0)">>;</span></div>
</code></div></div></blockquote><div><br></div><div>My prior proposal had s=
yntax for this sequence: ...N. This was also overloadable for user-defined =
types, so that (for instance) for a tuple t, '...t' could be sugar =
for 'get<...N>(t)'.</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px s=
olid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250=
)">
<code><div><span style><br></span><span style=3D"color:rgb(0,0,136)">templa=
te</span><span style> </span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style>size_t N</span><span style=3D"color:rgb(102,102,0)">></spa=
n><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> size=
_t</span><span style=3D"color:rgb(102,102,0)">...</span><span style> make_i=
ndex_pack </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=
> make_integer_pack</span><span style=3D"color:rgb(102,102,0)"><</span><=
span style>size_t</span><span style=3D"color:rgb(102,102,0)">,</span><span =
style> N</span><span style=3D"color:rgb(102,102,0)">>;</span><span style=
><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> size=
_t</span><span style=3D"color:rgb(102,102,0)">...</span><span style> index_=
pack_for </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style>=
make_index_pack</span><span style=3D"color:rgb(102,102,0)"><</span><spa=
n style=3D"color:rgb(0,0,136)">sizeof</span><span style=3D"color:rgb(102,10=
2,0)">...(</span><span style>T</span><span style=3D"color:rgb(102,102,0)">)=
>;</span></div>
</code></div><div>=A0</div><p>With these variable template packs, additiona=
l utilies can be provided for tuple-like classes:</p><div style=3D"border:1=
px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250=
,250)">
<code><div><span style=3D"color:rgb(136,0,0)">// tuple_indices<T> is =
equivalenent to 0, 1, ..., tuple_size<T>::value - 1</span><span style=
><br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> =
</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color=
:rgb(0,0,136)">class</span><span style> T</span><span style=3D"color:rgb(10=
2,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> size=
_t</span><span style=3D"color:rgb(102,102,0)">...</span><span style> tuple_=
indices </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> =
make_index_pack</span><span style=3D"color:rgb(102,102,0)"><</span><span=
style>tuple_size</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style>T</span><span style=3D"color:rgb(102,102,0)">>::</span><span st=
yle>value</span><span style=3D"color:rgb(102,102,0)">>;</span><span styl=
e><br>
<br></span><span style=3D"color:rgb(136,0,0)">// tuple_elements<T> is=
equivalent to tuple_element_t<0, T>, tuple_element_t<1, T>, ..=
.., tuple_element_t<N-1, T></span><span style><br></span><span style=
=3D"color:rgb(0,0,136)">template</span><span style> </span><span style=3D"c=
olor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</s=
pan><span style> T</span><span style=3D"color:rgb(102,102,0)">></span><s=
pan style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> tuple_elements </span><span style=3D=
"color:rgb(102,102,0)">=3D</span><span style> tuple_element_t</span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span style>tuple_indices</span><s=
pan style=3D"color:rgb(102,102,0)"><</span><span style>T</span><span sty=
le=3D"color:rgb(102,102,0)">>,</span><span style> T</span><span style=3D=
"color:rgb(102,102,0)">>;</span></div>
</code></div><p><br>These are much more simpler to use than current workaro=
unds requiring usage of std::integer_sequence. Example of passing all eleme=
nts of tuple t as arguments to a function f:</p><div style=3D"border:1px so=
lid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)=
">
<code><div><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> </span><span style=3D"color:rgb(102,0,102)">Args</span><span sty=
le=3D"color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,=
102)">Args</span><span style=3D"color:rgb(102,102,0)">&&...</span><=
span style> args</span><span style=3D"color:rgb(102,102,0)">);</span><span =
style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style> </span><span style=3D"color:rgb(102,=
0,102)">Tuple</span><span style=3D"color:rgb(102,102,0)">></span><span s=
tyle><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> g</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">&&</span><span style> t</span><span style=
=3D"color:rgb(102,102,0)">)</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0f</s=
pan><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0=
,0,136)">get</span><span style=3D"color:rgb(102,102,0)"><</span><span st=
yle>tuple_indices</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style>T</span><span style=3D"color:rgb(102,102,0)">>>(</span><span=
style>forward</span><span style=3D"color:rgb(102,102,0)"><</span><span =
style>T</span><span style=3D"color:rgb(102,102,0)">>(</span><span style>=
t</span><span style=3D"color:rgb(102,102,0)">))...);</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div></di=
v></blockquote><div>=A0</div><div>This is still a little unclean. My propos=
al supports this as:</div><div><br></div><div>=A0 f(...std::forward<T>=
;(t) ...);</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p></p><p><strong><font size=3D"4">Return=
ing a pack from a function</font></strong></p>
<p>With pack variables comes the need for functions returning a pack of val=
ues.</p></div></blockquote><div><br></div><div>Why not return a tuple? Pack=
s are not types, so functions returning packs doesn't really seem to ma=
ke much sense.</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><p>The most basic function =
that could be defined is one returning a pack from several values:</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span style> </span><span style=3D"color:rgb(102,102,0)"><=
;</span><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color=
:rgb(102,102,0)">...</span><span style> T</span><span style=3D"color:rgb(10=
2,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">decltype</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">auto</span><s=
pan style=3D"color:rgb(102,102,0)">)...</span><span style> make_pack</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span styl=
e=3D"color:rgb(102,102,0)">&&...</span><span style> t</span><span s=
tyle=3D"color:rgb(102,102,0)">)</span><span style> </span><span style=3D"co=
lor:rgb(102,102,0)">{</span><span style> </span><span style=3D"color:rgb(0,=
0,136)">return</span><span style> forward</span><span style=3D"color:rgb(10=
2,102,0)"><</span><span style>T</span><span style=3D"color:rgb(102,102,0=
)">>(</span><span style>t</span><span style=3D"color:rgb(102,102,0)">);<=
/span><span style> </span><span style=3D"color:rgb(102,102,0)">}</span></di=
v>
</code></div><div>=A0</div><div>Usage example:</div><div>=A0</div><div styl=
e=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-colo=
r:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">void</spa=
n><span style> g</span><span style=3D"color:rgb(102,102,0)">(</span><span s=
tyle=3D"color:rgb(0,0,136)">int</span><span style> a</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style> </span><span style=3D"color:rgb(0=
,0,136)">int</span><span style> b</span><span style=3D"color:rgb(102,102,0)=
">,</span><span style> </span><span style=3D"color:rgb(0,0,136)">int</span>=
<span style> c</span><span style=3D"color:rgb(102,102,0)">,</span><span sty=
le> </span><span style=3D"color:rgb(0,0,136)">int</span><span style> d</spa=
n><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><span st=
yle=3D"color:rgb(0,0,136)">int</span><span style> e</span><span style=3D"co=
lor:rgb(102,102,0)">,</span><span style> </span><span style=3D"color:rgb(0,=
0,136)">int</span><span style> f</span><span style=3D"color:rgb(102,102,0)"=
>,</span><span style> </span><span style=3D"color:rgb(0,0,136)">int</span><=
span style> g</span><span style=3D"color:rgb(102,102,0)">,</span><span styl=
e> </span><span style=3D"color:rgb(0,0,136)">int</span><span style> h</span=
><span style=3D"color:rgb(102,102,0)">);</span><span style><br>
<br></span><span style=3D"color:rgb(136,0,0)">// Following functions forwar=
d all arguments to g by first multiplying them by 2 and adding 3</span><spa=
n style><br></span><span style=3D"color:rgb(0,0,136)">void</span><span styl=
e> f</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"colo=
r:rgb(0,0,136)">int</span><span style> a</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style> </span><span style=3D"color:rgb(0,0,136)">int=
</span><span style> b</span><span style=3D"color:rgb(102,102,0)">,</span><s=
pan style> </span><span style=3D"color:rgb(0,0,136)">int</span><span style>=
c</span><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><=
span style=3D"color:rgb(0,0,136)">int</span><span style> d</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style> </span><span style=3D"color=
:rgb(0,0,136)">int</span><span style> e</span><span style=3D"color:rgb(102,=
102,0)">,</span><span style> </span><span style=3D"color:rgb(0,0,136)">int<=
/span><span style> f</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an style> </span><span style=3D"color:rgb(0,0,136)">int</span><span style> =
g</span><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><s=
pan style=3D"color:rgb(0,0,136)">int</span><span style> h</span><span style=
=3D"color:rgb(102,102,0)">)</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0</sp=
an><span style=3D"color:rgb(136,0,0)">// Old way</span><span style><br>=A0g=
</span><span style=3D"color:rgb(102,102,0)">(</span><span style>a</span><sp=
an style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,10=
2)">2</span><span style> </span><span style=3D"color:rgb(102,102,0)">+</spa=
n><span style> </span><span style=3D"color:rgb(0,102,102)">3</span><span st=
yle=3D"color:rgb(102,102,0)">,</span><span style> b</span><span style=3D"co=
lor:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><s=
pan style> </span><span style=3D"color:rgb(102,102,0)">+</span><span style>=
</span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:r=
gb(102,102,0)">,</span><span style> c</span><span style=3D"color:rgb(102,10=
2,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span style> </s=
pan><span style=3D"color:rgb(102,102,0)">+</span><span style> </span><span =
style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)"=
>,</span><span style> d</span><span style=3D"color:rgb(102,102,0)">*</span>=
<span style=3D"color:rgb(0,102,102)">2</span><span style> </span><span styl=
e=3D"color:rgb(102,102,0)">+</span><span style> </span><span style=3D"color=
:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><span=
style> e</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D=
"color:rgb(0,102,102)">2</span><span style> </span><span style=3D"color:rgb=
(102,102,0)">+</span><span style> </span><span style=3D"color:rgb(0,102,102=
)">3</span><span style=3D"color:rgb(102,102,0)">,</span><span style> f</spa=
n><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,1=
02,102)">2</span><span style> </span><span style=3D"color:rgb(102,102,0)">+=
</span><span style> </span><span style=3D"color:rgb(0,102,102)">3</span><sp=
an style=3D"color:rgb(102,102,0)">,</span><span style> g</span><span style=
=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</s=
pan><span style> </span><span style=3D"color:rgb(102,102,0)">+</span><span =
style> </span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style> h</span><span style=3D"color:rgb(=
102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span styl=
e> </span><span style=3D"color:rgb(102,102,0)">+</span><span style> </span>=
<span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,1=
02,0)">);</span><span style><br>
=A0</span><span style=3D"color:rgb(136,0,0)">// New way</span><span style><=
br>=A0g</span><span style=3D"color:rgb(102,102,0)">(</span><span style>make=
_pack</span><span style=3D"color:rgb(102,102,0)">(</span><span style>a</spa=
n><span style=3D"color:rgb(102,102,0)">,</span><span style> b</span><span s=
tyle=3D"color:rgb(102,102,0)">,</span><span style> c</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style> d</span><span style=3D"color:rgb(=
102,102,0)">,</span><span style> e</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style> f</span><span style=3D"color:rgb(102,102,0)">,</spa=
n><span style> g</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle> h</span><span style=3D"color:rgb(102,102,0)">)*</span><span style=3D"=
color:rgb(0,102,102)">2</span><span style> </span><span style=3D"color:rgb(=
102,102,0)">+</span><span style> </span><span style=3D"color:rgb(0,102,102)=
">3</span><span style> </span><span style=3D"color:rgb(102,102,0)">...);</s=
pan></div>
</code></div></div></blockquote><div><br></div><div>Again, this has the pro=
blem of not syntactically identifying what's a pack and what's not.=
With my syntax:</div><div><br></div><div>=A0 g(...tie(a, b, c, d, e, f, g,=
h)*2 + 3...);</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px s=
olid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250=
)">
<code><div><span style><br></span><span style=3D"color:rgb(102,102,0)">}</s=
pan></div></code></div><br><p>Another usage would be a function returning a=
ll the values of a tuple-like class:</p><p></p><div style=3D"border:1px sol=
id rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"=
>
<code><div><span style=3D"color:rgb(136,0,0)">// get_all(t) is equivalent t=
o get<0>(t), get<1>(t), ..., get<N-1>(t)</span><span styl=
e><br></span><span style=3D"color:rgb(0,0,136)">template</span><span style>=
</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"colo=
r:rgb(0,0,136)">class</span><span style> T</span><span style=3D"color:rgb(1=
02,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span style> </sp=
an><span style=3D"color:rgb(0,0,136)">decltype</span><span style=3D"color:r=
gb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">auto</span><span =
style=3D"color:rgb(102,102,0)">)...</span><span style> get_all</span><span =
style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=3D"c=
olor:rgb(102,102,0)">&&</span><span style> t</span><span style=3D"c=
olor:rgb(102,102,0)">)</span><span style> </span><span style=3D"color:rgb(1=
02,102,0)">{</span><span style> </span><span style=3D"color:rgb(0,0,136)">r=
eturn</span><span style> </span><span style=3D"color:rgb(0,0,136)">get</spa=
n><span style=3D"color:rgb(102,102,0)"><</span><span style>tuple_indices=
</span><span style=3D"color:rgb(102,102,0)"><</span><span style>T</span>=
<span style=3D"color:rgb(102,102,0)">>>(</span><span style>forward</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span style>T</span><sp=
an style=3D"color:rgb(102,102,0)">>(</span><span style>t</span><span sty=
le=3D"color:rgb(102,102,0)">));</span><span style> </span><span style=3D"co=
lor:rgb(102,102,0)">}</span></div>
</code></div><br>Usage example (passing all elements of tuple t as argument=
s to a function f):<p></p><div style=3D"border:1px solid rgb(187,187,187);w=
ord-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span sty=
le=3D"color:rgb(0,0,136)">template</span><span style> </span><span style=3D=
"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class<=
/span><span style=3D"color:rgb(102,102,0)">...</span><span style> T</span><=
span style=3D"color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">&&...</span><span style> t</span><span st=
yle=3D"color:rgb(102,102,0)">);</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style> </span><span style=3D"color:rgb(102,=
0,102)">Tuple</span><span style=3D"color:rgb(102,102,0)">></span><span s=
tyle><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span style> g</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">&&</span><span style> t</span><span style=
=3D"color:rgb(102,102,0)">)</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style><br>=A0f</s=
pan><span style=3D"color:rgb(102,102,0)">(</span><span style>get_all</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span style>forward</span><spa=
n style=3D"color:rgb(102,102,0)"><</span><span style>T</span><span style=
=3D"color:rgb(102,102,0)">>(</span><span style>t</span><span style=3D"co=
lor:rgb(102,102,0)">))...);</span><span style><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><p>=
=A0</p><p><font size=3D"4"><strong>Expanding nested pack aliases</strong></=
font></p><p>Considering the following:</p><div style=3D"border:1px solid rg=
b(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> original </span><span style=3D"c=
olor:rgb(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"=
color:rgb(102,102,0)"><</span><span style>T0</span><span style=3D"color:=
rgb(102,102,0)">,</span><span style> T1</span><span style=3D"color:rgb(102,=
102,0)">,</span><span style> </span><span style=3D"color:rgb(136,0,0)">/*..=
..*/</span><span style=3D"color:rgb(102,102,0)">,</span><span style> TN</spa=
n><span style=3D"color:rgb(102,102,0)">>;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> </span><span style=3D"color:rgb(0,0,=
136)">alias</span><span style> </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style> </span><span style=3D"color:rgb(136,0,0)">/*...*/</s=
pan><span style=3D"color:rgb(102,102,0)">;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> a </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> </span><span style=3D"color:rgb(0,0,13=
6)">alias</span><span style=3D"color:rgb(102,102,0)"><</span><span style=
>original</span><span style=3D"color:rgb(102,102,0)">...>;</span><span s=
tyle><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> b </span><span style=3D"color:rgb(10=
2,102,0)">=3D</span><span style> </span><span style=3D"color:rgb(0,0,136)">=
alias</span><span style=3D"color:rgb(0,136,0)"><original></span><span=
style=3D"color:rgb(102,102,0)">...;</span></div>
</code></div><p><br>The pack a is the result of applying the alias on the e=
ntire original pack.<br>The pack b is the result of applying the alias on e=
ach individual elements of the original pack.</p><p></p><div style=3D"borde=
r:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,=
250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> a </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> </span><span style=3D"color:rgb(0,0,13=
6)">alias</span><span style=3D"color:rgb(102,102,0)"><</span><span style=
>T0</span><span style=3D"color:rgb(102,102,0)">,</span><span style> T1</spa=
n><span style=3D"color:rgb(102,102,0)">,</span><span style> </span><span st=
yle=3D"color:rgb(136,0,0)">/*...*/</span><span style=3D"color:rgb(102,102,0=
)">,</span><span style> TN</span><span style=3D"color:rgb(102,102,0)">>;=
</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> b </span><span style=3D"color:rgb(10=
2,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:rgb(1=
02,102,0)"><</span><span style=3D"color:rgb(0,0,136)">alias</span><span =
style=3D"color:rgb(102,102,0)"><</span><span style>T0</span><span style=
=3D"color:rgb(102,102,0)">>...,</span><span style> </span><span style=3D=
"color:rgb(0,0,136)">alias</span><span style=3D"color:rgb(102,102,0)"><<=
/span><span style>T1</span><span style=3D"color:rgb(102,102,0)">>...,</s=
pan><span style> </span><span style=3D"color:rgb(136,0,0)">/*...*/</span><s=
pan style=3D"color:rgb(102,102,0)">,</span><span style> </span><span style=
=3D"color:rgb(0,0,136)">alias</span><span style=3D"color:rgb(102,102,0)">&l=
t;</span><span style>TN</span><span style=3D"color:rgb(102,102,0)">>...&=
gt;;</span></div>
</code></div><br>When multiple aliases are used, the same rules can be appl=
ied successively by considering the inner-most pack first.<br>The following=
example illustrates how the rules are applied when 2 aliases are used on a=
pack.<p>
</p><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;ba=
ckground-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,13=
6)">using</span><span style=3D"color:rgb(102,102,0)">...</span><span style>=
orig </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style> ty=
pe_pack</span><span style=3D"color:rgb(102,102,0)"><</span><span style>T=
0</span><span style=3D"color:rgb(102,102,0)">,</span><span style> T1</span>=
<span style=3D"color:rgb(102,102,0)">,</span><span style> </span><span styl=
e=3D"color:rgb(136,0,0)">/*...*/</span><span style=3D"color:rgb(102,102,0)"=
>,</span><span style> TN</span><span style=3D"color:rgb(102,102,0)">>;</=
span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> a1 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> </span><span style=3D"color:rgb(136,0,0)"=
>/*...*/</span><span style=3D"color:rgb(102,102,0)">;</span><span style><br=
>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style> <=
/span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><s=
pan style> T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> a2 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> </span><span style=3D"color:rgb(136,0,0)"=
>/*...*/</span><span style=3D"color:rgb(102,102,0)">;</span><span style><br=
>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> a </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> a1</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>a2</span><span style=3D"color:rgb(102,102,0)=
"><</span><span style>orig</span><span style=3D"color:rgb(102,102,0)">..=
..>...>;</span><span style><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig...>;</span><span style><br></span><span style=3D"color:rgb(136,0=
,0)">// =A0 =A0 =A0 =A0 =A0using... a =3D a1<temp...>;</span><span st=
yle><br><br></span><span style=3D"color:rgb(0,0,136)">using</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span style> b </span><span style=3D"=
color:rgb(102,102,0)">=3D</span><span style> a1</span><span style=3D"color:=
rgb(102,102,0)"><</span><span style>a2</span><span style=3D"color:rgb(0,=
136,0)"><orig></span><span style=3D"color:rgb(102,102,0)">...</span><=
span style> </span><span style=3D"color:rgb(102,102,0)">...>;</span><spa=
n style><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig>...;</span><span style><br></span><span style=3D"color:rgb(136,0=
,0)">// =A0 =A0 =A0 =A0 =A0using... b =3D a1<temp...>;</span><span st=
yle><br><br></span><span style=3D"color:rgb(0,0,136)">using</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span style> c </span><span style=3D"=
color:rgb(102,102,0)">=3D</span><span style> a1</span><span style=3D"color:=
rgb(102,102,0)"><</span><span style>a2</span><span style=3D"color:rgb(10=
2,102,0)"><</span><span style>orig</span><span style=3D"color:rgb(102,10=
2,0)">...>>...;</span><span style><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig...>;</span><span style><br></span><span style=3D"color:rgb(136,0=
,0)">// =A0 =A0 =A0 =A0 =A0using... c =3D a1<temp>...;</span><span st=
yle><br><br></span><span style=3D"color:rgb(0,0,136)">using</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span style> d </span><span style=3D"=
color:rgb(102,102,0)">=3D</span><span style> a1</span><span style=3D"color:=
rgb(102,102,0)"><</span><span style>a2</span><span style=3D"color:rgb(0,=
136,0)"><orig></span><span style=3D"color:rgb(102,102,0)">...>...;=
</span><span style><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig>...;</span><span style><br></span><span style=3D"color:rgb(136,0=
,0)">// =A0 =A0 =A0 =A0 =A0using... d =3D a1<temp>...;</span><span st=
yle><br><br></span><span style=3D"color:rgb(136,0,0)">//using... e =3D a1&l=
t;a2<orig>>... ...;</span><span style><br>
</span><span style=3D"color:rgb(136,0,0)">// error</span><span style><br><b=
r></span><span style=3D"color:rgb(136,0,0)">//using... f =3D a1<a2<or=
ig... ...>>;</span><span style><br></span><span style=3D"color:rgb(13=
6,0,0)">// error</span></div>
</code></div><p><br>Additional examples</p><div style=3D"border:1px solid r=
gb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><co=
de><div><span style=3D"color:rgb(0,0,136)">struct</span><span style> A </sp=
an><span style=3D"color:rgb(102,102,0)">{};</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">struct</span><span style> B </spa=
n><span style=3D"color:rgb(102,102,0)">{};</span><span style><br><br></span=
><span style=3D"color:rgb(0,0,136)">template</span><span style> </span><spa=
n style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,13=
6)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span style>=
T</span><span style=3D"color:rgb(102,102,0)">></span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> twice </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:r=
gb(102,102,0)"><</span><span style>T</span><span style=3D"color:rgb(102,=
102,0)">...,</span><span style> T</span><span style=3D"color:rgb(102,102,0)=
">...>;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> AB </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:=
rgb(102,102,0)"><</span><span style>A</span><span style=3D"color:rgb(102=
,102,0)">,</span><span style> B</span><span style=3D"color:rgb(102,102,0)">=
>;</span><span style> =A0 =A0 =A0 =A0 =A0 =A0 </span><span style=3D"colo=
r:rgb(136,0,0)">// A, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t1 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)=
">...>;</span><span style> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0</span><span s=
tyle=3D"color:rgb(136,0,0)">// A, B, A, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t2 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:rgb(=
102,102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102=
,102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0=
)">...>...>;</span><span style> =A0</span><span style=3D"color:rgb(13=
6,0,0)">// A, B, A, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t3 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)=
">>...;</span><span style> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0</span><span s=
tyle=3D"color:rgb(136,0,0)">// A, A, B, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t4 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:rgb(=
102,102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102=
,102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0=
)">>...</span><span style> </span><span style=3D"color:rgb(102,102,0)">.=
...>;</span><span style> </span><span style=3D"color:rgb(136,0,0)">// A, =
A, B, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t5 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>...>;</span><span style> =A0 =A0 =A0</span><span style=3D"color:rg=
b(136,0,0)">// A, B, A, B, A, B, A, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t6 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...</span><span style> </span><span style=3D"color:rgb(102,102,0)">...&g=
t;;</span><span style> =A0 =A0 </span><span style=3D"color:rgb(136,0,0)">//=
A, A, B, B, A, A, B, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t7 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>>...;</span><span style> =A0 =A0 =A0</span><span style=3D"color:rg=
b(136,0,0)">// A, A, B, B, A, A, B, B</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> t8 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...>...;</span><span style> =A0 =A0 =A0</span><span style=3D"color:rg=
b(136,0,0)">// A, A, A, A, B, B, B, B</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">struct</span><span style> C <=
/span><span style=3D"color:rgb(102,102,0)">{};</span><span style><br><br></=
span><span style=3D"color:rgb(0,0,136)">template</span><span style> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span st=
yle> T</span><span style=3D"color:rgb(102,102,0)">></span><span style><b=
r>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> add_c </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style> type_pack</span><span style=3D"color:r=
gb(102,102,0)"><</span><span style>T</span><span style=3D"color:rgb(102,=
102,0)">...,</span><span style> C</span><span style=3D"color:rgb(102,102,0)=
">>;</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> u1 </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(=
102,102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,10=
2,0)">...>;</span><span style> =A0 =A0 =A0 =A0 =A0 =A0</span><span style=
=3D"color:rgb(136,0,0)">// A, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> u2 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)=
">>...;</span><span style> =A0 =A0 =A0 =A0 =A0 =A0</span><span style=3D"=
color:rgb(136,0,0)">// A, C, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> u3 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>...>;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, B, C, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> u4 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...</span><span style> </span><span style=3D"color:rgb(102,102,0)">...&g=
t;;</span><span style> </span><span style=3D"color:rgb(136,0,0)">// A, C, B=
, C, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> u5 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, C, B, C, C, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> u6 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, C, C, C, B, C, C, C</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> v1 </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(=
102,102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102=
,102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0=
)">...>...>;</span><span style> =A0</span><span style=3D"color:rgb(13=
6,0,0)">// A, B, A, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> v2 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...</span><span style> </span><span style=3D"color:rgb(102,102,0)">...&g=
t;;</span><span style> </span><span style=3D"color:rgb(136,0,0)">// A, A, B=
, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> v3 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, C, B, C, A, C, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> v4 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>twice</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, C, A, C, B, C, B, C</span><span style><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span style> w1 </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(=
102,102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102=
,102,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0=
)">...>...>;</span><span style> =A0</span><span style=3D"color:rgb(13=
6,0,0)">// A, B, C, A, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> w2 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...</span><span style> </span><span style=3D"color:rgb(102,102,0)">...&g=
t;;</span><span style> </span><span style=3D"color:rgb(136,0,0)">// A, C, B=
, C, A, C, B, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> w3 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">.=
...>>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, A, B, B, C, C</span><span style><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span style> w4 </span><span style=3D"color:rgb(1=
02,102,0)">=3D</span><span style> twice</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style>add_c</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style>AB</span><span style=3D"color:rgb(102,102,0)">&=
gt;...>...;</span><span style> =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, A, C, C, B, B, C, C</span></div>
</code></div><span class=3D""><font color=3D"#888888"><p>=A0</p></font></sp=
an><p></p><p></p></div><span class=3D""><font color=3D"#888888">
<p></p>
-- <br>
=A0<br>
--- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br><br>
</font></span></blockquote></div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bdc051e89cf9f04ebc9ed3a--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Fri, 22 Nov 2013 12:36:52 -0800
Raw View
--20cf3079bfb8699c5704ebc9f944
Content-Type: text/plain; charset=ISO-8859-1
On Fri, Nov 22, 2013 at 12:33 PM, Richard Smith <richard@metafoo.co.uk>wrote:
> On Fri, Nov 22, 2013 at 11:36 AM, Alex B <devalexb@gmail.com> wrote:
>
>> Hi,
>>
>> I have been working on several ideas that would fill several gaps and
>> make things much easier when dealing with parameter packs. Before going in
>> with a formal proposal, I first wanted to share my ideas. Feedback would be
>> greatly appreciated.
>>
>> *Type pack alias*
>>
>> A pack alias (templated or not) can be defined with a "using..."
>> directive. On the right hand side must be an unexpanded type pack. This
>> unexpanded type pack can come from an unexpanded parameter pack of a
>> variadic template or from another pack alias.
>>
>>
>> A pack alias can be expanded with the "..." operator in the same way as
>> an unexanded parameter pack of a variadic template.
>>
>> The most basic (and useful) templated pack alias would be the following,
>> which allow creating packs on the fly:
>> template <class... T>
>> using... type_pack = T;
>>
>>
>>
>> Usage example:
>> using... my_types = type_pack<int, char, double>;
>> using my_tuple = tuple<my_types...>;
>>
>>
> This immediately creates a problem. One of the properties of packs today
> is that it is possible to syntactically determine whether some snippet of
> C++ syntax contains unexpanded parameter packs, and to determine which
> packs it contains. This is crucial to some implementation techniques.
>
> It's also important in resolving some grammar ambiguities. Today, if I
> have:
>
> template<typename T> void f(typename T::type x ...);
>
> I know this is a vararg function. With your proposal, I could presumably
> write:
>
> template<typename...Ts> struct X {
> using ...type = Ts;
> };
> void g() {
> f<X<int, int, int>>(1, 2, 3);
> }
>
> and 'f' would mean something fundamentally different.
>
> I had a similar-but-different proposal a while back (which I've not
> written up for committee consideration yet) which avoids this problem by
> using a slightly different syntax:
>
> template<typename...Ts> struct types {
> using ... = Ts; // "...types<Ts>" is the pack "Ts"
> };
>
> typedef std::types<int, char, double> icd; // just a normal type
> void f(...icd ...x) // "...icd" is a pack of types; this is "void f(int,
> char, double)" except that we have a pack of parameters
>
> *Variable pack*
>>
>>
>> Variable packs are the same as function parameter packs, except that they
>> can be declared anywhere a variable can be declared. There are two ways to
>> declare and initialize a variable pack.
>>
>> The first one is by using an already defined type pack. If constructor
>> arguments are specified as single values, all the constructors of the
>> variables in the pack are called with those same arguments.
>> using... types = type_pack<int, char, double>;
>> types values1;
>>
>
> This syntax doesn't work. Consider:
>
> template<typename ...Ts>
> void f(Ts ...ts) {
> g(ts + []() {
> types values;
> return values;
> }() ...);
> }
>
> This would be ambiguous: does each lambda declare a *pack* of values, or a
> *slice* of that pack of values? The way to fix this is to consistently use
> pack expansion whenever you expand a pack:
>
> // assuming 'types' names a pack of types
> types ...values1; // ok, declare a pack of values named 'values1'.
>
> This would still be problematic if you allowed pack expansions as a static
> or non-static data member, because of the above-mentioned problem with
> being unable to syntactically determine what is and is not a pack.
>
>
>> type_pack<int, char, double> values2;
>> types values3 = 10; // all 3 variables are initialized to 10
>> types values4(10); // same
>> types values5 = values2;
>> type_pack<double, double, double> values6 = values2;
>> //type_pack<int, char> values7 = values2; //error: mismatching pack sizes
>>
>> template <class... T>
>> class C
>> {
>> T... values;
>>
>
> This, for instance, is a problem, because X::values (for a dependent type
> X) might or might not be a pack if this were valid.
>
>
>>
>> };
>>
>> template <class... T>
>> void f(T... t)
>> {
>> T... t2 = t * 2;
>> }
>>
>>
>> A variable pack can also be declared without a defined type pack. In that
>> case, it must be initialized from another variable pack.
>>
>> //double... values8; //error: unknown pack size
>> //double... values9 = 10.0; //error: unknown pack size
>> double... values10 = values2; // pack of 3 variables of type double
>> double... values11(values2); // same
>>
>
> Seems fine to me: the pack expansion includes 'values2', so can infer its
> length from there.
>
>
>>
>> auto... values12 = values2; // pack of 3 variables of types int, char
>> and double
>>
>
> Presumably this means that your expansion model is that this expands to
>
> auto values12$0 = values2$0;
> auto values12$1 = values2$1;
> auto vaules12$2 = values2$2;
>
> not the more natural choice of
>
> auto values12$0 = values2$0, values12$1 = values2$1, vaules12$2 =
> values2$2;
>
> (which would be ill-formed, because the 'auto' deduces to different types
> in different deductions).
>
>
>>
>>
>>
>> template <class... T>
>> void g(T... t)
>> {
>> auto... t2 = t * 2;
>> }
>>
>>
>> Operations can be done on packs if all the unexpanded packs are of the
>> same size.
>> values10 = values11 * 2.0;
>> values11 += values10;
>> values11 = values10 + values11;
>>
>
> Again, this doesn't work, due to ambiguity over where the expansion
> happens. Instead, I'd suggest (and indeed, have been intending to propose
> for standardization) adding an optional '...' before the ';' in an
> expression-statement, to represent a pack expansion. So you'd write:
>
> values10 = values11 * 2.0 ...;
>
> and it would be equivalent to today's
>
> sink{ values10 = values11 * 2.0 ... };
>
> (for an appropriately-defined class 'sink')
>
>> Single values can be used along with pack but only in operations in which
>> those single values are const.
>> double single_value = 1.0;
>> values10 *= single_value; //ok: rhs is const single_value
>> single_value *= values10; //error: lhs of operator*= cannot be const
>>
>> void h(const double&, double&) {}
>>
>> h(values10, values11); //ok: 2 packs of the same size (h will be called
>> 3 times)
>> h(single_value, values10); //ok: first arg of h is const (h will be
>> called 3 times, each time with the same single_value)
>> h(values10, single_value); //error: trying to pass a non-const single
>> value in an unexpanded context
>>
>>
>>
>> *Variable template pack*
>>
>> Variable packs should also work for variable templates.
>>
>> The most basic (and useful) variable template packs would be an
>> equivalent to std::integer_sequence that would allow working directly with
>> an integer pack (instead of having to store that pack in a type).
>> template <class T, T... I>
>> constexpr T... integer_pack = I;
>>
>> template <size_t... I>
>> constexpr size_t... index_pack = I;
>>
>> template <class T, T N>
>> constexpr T... make_integer_pack = integer_pack<T, /* a sequence 0, 1,
>> 2, ..., N-1 */>;
>>
>
> My prior proposal had syntax for this sequence: ...N. This was also
> overloadable for user-defined types, so that (for instance) for a tuple t,
> '...t' could be sugar for 'get<...N>(t)'.
>
To save you the effort of digging it up:
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/g1HziHt1lbo/RHxb2fxKt5IJ
>
>
>> template <size_t N>
>> constexpr size_t... make_index_pack = make_integer_pack<size_t, N>;
>>
>> template <class... T>
>> constexpr size_t... index_pack_for = make_index_pack<sizeof...(T)>;
>>
>>
>> With these variable template packs, additional utilies can be provided
>> for tuple-like classes:
>> // tuple_indices<T> is equivalenent to 0, 1, ..., tuple_size<T>::value - 1
>> template <class T>
>> constexpr size_t... tuple_indices = make_index_pack<tuple_size<T>::value
>> >;
>>
>> // tuple_elements<T> is equivalent to tuple_element_t<0, T>,
>> tuple_element_t<1, T>, ..., tuple_element_t<N-1, T>
>> template <class T>
>> using... tuple_elements = tuple_element_t<tuple_indices<T>, T>;
>>
>>
>> These are much more simpler to use than current workarounds requiring
>> usage of std::integer_sequence. Example of passing all elements of tuple t
>> as arguments to a function f:
>> template <class... Args>
>> void f(Args&&... args);
>>
>> template <class Tuple>
>> void g(T&& t)
>> {
>> f(get<tuple_indices<T>>(forward<T>(t))...);
>> }
>>
>
> This is still a little unclean. My proposal supports this as:
>
> f(...std::forward<T>(t) ...);
>
>> *Returning a pack from a function*
>>
>> With pack variables comes the need for functions returning a pack of
>> values.
>>
>
> Why not return a tuple? Packs are not types, so functions returning packs
> doesn't really seem to make much sense.
>
>
>> The most basic function that could be defined is one returning a pack
>> from several values:
>> template <class... T>
>> decltype(auto)... make_pack(T&&... t) { return forward<T>(t); }
>>
>> Usage example:
>>
>> void g(int a, int b, int c, int d, int e, int f, int g, int h);
>>
>> // Following functions forward all arguments to g by first multiplying
>> them by 2 and adding 3
>> void f(int a, int b, int c, int d, int e, int f, int g, int h)
>> {
>> // Old way
>> g(a*2 + 3, b*2 + 3, c*2 + 3, d*2 + 3, e*2 + 3, f*2 + 3, g*2 + 3, h*2 + 3
>> );
>> // New way
>> g(make_pack(a, b, c, d, e, f, g, h)*2 + 3 ...);
>>
>
> Again, this has the problem of not syntactically identifying what's a pack
> and what's not. With my syntax:
>
> g(...tie(a, b, c, d, e, f, g, h)*2 + 3...);
>
>
>> }
>>
>> Another usage would be a function returning all the values of a
>> tuple-like class:
>>
>> // get_all(t) is equivalent to get<0>(t), get<1>(t), ..., get<N-1>(t)
>> template <class T>
>> constexpr decltype(auto)... get_all(T&& t) { return get<tuple_indices<T
>> >>(forward<T>(t)); }
>>
>> Usage example (passing all elements of tuple t as arguments to a function
>> f):
>>
>> template <class... T>
>> void f(T&&... t);
>>
>> template <class Tuple>
>> void g(T&& t)
>> {
>> f(get_all(forward<T>(t))...);
>> }
>>
>>
>>
>> *Expanding nested pack aliases*
>>
>> Considering the following:
>> using... original = type_pack<T0, T1, /*...*/, TN>;
>>
>> template <class... T>
>> using... alias = /*...*/;
>>
>> using... a = alias<original...>;
>> using... b = alias<original>...;
>>
>>
>> The pack a is the result of applying the alias on the entire original
>> pack.
>> The pack b is the result of applying the alias on each individual
>> elements of the original pack.
>>
>> using... a = alias<T0, T1, /*...*/, TN>;
>> using... b = type_pack<alias<T0>..., alias<T1>..., /*...*/, alias<TN
>> >...>;
>>
>> When multiple aliases are used, the same rules can be applied
>> successively by considering the inner-most pack first.
>> The following example illustrates how the rules are applied when 2
>> aliases are used on a pack.
>>
>> using... orig = type_pack<T0, T1, /*...*/, TN>;
>>
>> template <class... T>
>> using... a1 = /*...*/;
>>
>> template <class... T>
>> using... a2 = /*...*/;
>>
>> using... a = a1<a2<orig...>...>;
>> // same as: using... temp = a2<orig...>;
>> // using... a = a1<temp...>;
>>
>> using... b = a1<a2<orig>... ...>;
>> // same as: using... temp = a2<orig>...;
>> // using... b = a1<temp...>;
>>
>> using... c = a1<a2<orig...>>...;
>> // same as: using... temp = a2<orig...>;
>> // using... c = a1<temp>...;
>>
>> using... d = a1<a2<orig>...>...;
>> // same as: using... temp = a2<orig>...;
>> // using... d = a1<temp>...;
>>
>> //using... e = a1<a2<orig>>... ...;
>> // error
>>
>> //using... f = a1<a2<orig... ...>>;
>> // error
>>
>>
>> Additional examples
>> struct A {};
>> struct B {};
>>
>> template <class... T>
>> using... twice = type_pack<T..., T...>;
>>
>> using... AB = type_pack<A, B>; // A, B
>> using... t1 = twice<AB...>; // A, B, A, B
>> using... t2 = type_pack<twice<AB...>...>; // A, B, A, B
>> using... t3 = twice<AB>...; // A, A, B, B
>> using... t4 = type_pack<twice<AB>... ...>; // A, A, B, B
>> using... t5 = twice<twice<AB...>...>; // A, B, A, B, A, B, A, B
>> using... t6 = twice<twice<AB>... ...>; // A, A, B, B, A, A, B, B
>> using... t7 = twice<twice<AB...>>...; // A, A, B, B, A, A, B, B
>> using... t8 = twice<twice<AB>...>...; // A, A, A, A, B, B, B, B
>>
>> struct C {};
>>
>> template <class... T>
>> using... add_c = type_pack<T..., C>;
>>
>> using... u1 = add_c<AB...>; // A, B, C
>> using... u2 = add_c<AB>...; // A, C, B, C
>> using... u3 = add_c<add_c<AB...>...>; // A, B, C, C
>> using... u4 = add_c<add_c<AB>... ...>; // A, C, B, C, C
>> using... u5 = add_c<add_c<AB...>>...; // A, C, B, C, C, C
>> using... u6 = add_c<add_c<AB>...>...; // A, C, C, C, B, C, C, C
>>
>> using... v1 = add_c<twice<AB...>...>; // A, B, A, B, C
>> using... v2 = add_c<twice<AB>... ...>; // A, A, B, B, C
>> using... v3 = add_c<twice<AB...>>...; // A, C, B, C, A, C, B, C
>> using... v4 = add_c<twice<AB>...>...; // A, C, A, C, B, C, B, C
>>
>> using... w1 = twice<add_c<AB...>...>; // A, B, C, A, B, C
>> using... w2 = twice<add_c<AB>... ...>; // A, C, B, C, A, C, B, C
>> using... w3 = twice<add_c<AB...>>...; // A, A, B, B, C, C
>> using... w4 = twice<add_c<AB>...>...; // A, A, C, C, B, B, C, C
>>
>>
>>
>> --
>>
>> ---
>> 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/.
>>
>>
--
---
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/.
--20cf3079bfb8699c5704ebc9f944
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Nov 22, 2013 at 12:33 PM, Richard Smith <span dir=
=3D"ltr"><<a href=3D"mailto:richard@metafoo.co.uk" target=3D"_blank">ric=
hard@metafoo.co.uk</a>></span> wrote:<br><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><div class=3D"im">On Fri, Nov 22, 2013 at=
11:36 AM, Alex B <span dir=3D"ltr"><<a href=3D"mailto:devalexb@gmail.co=
m" target=3D"_blank">devalexb@gmail.com</a>></span> wrote:<br>
</div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div class=3D"i=
m">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>Hi,</div><div>=A0</div><div>I have b=
een working on several ideas=A0that would fill several gaps and make things=
much easier when dealing with parameter packs. Before going in with a form=
al proposal, I first wanted to share my ideas. Feedback would be greatly ap=
preciated.</div>
<div><strong><font size=3D"4"></font></strong>=A0</div><div><font size=3D"4=
"><strong>Type pack alias</strong></font></div><div>=A0</div><div>A pack al=
ias (templated or not) can be defined with a "using..." directive=
.. On the right hand side must be an unexpanded type pack. This unexpanded t=
ype pack can come from an unexpanded parameter pack of a variadic template =
or from another pack alias.</div>
<div>=A0</div><p>A pack alias can be expanded with the "..." oper=
ator in the same way as an unexanded parameter pack of a variadic template.=
</p><p>The most basic (and useful) templated pack alias would be the follow=
ing, which allow creating packs on the fly:</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span> </span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(1=
02,102,0)">...</span><span> T</span><span style=3D"color:rgb(102,102,0)">&g=
t;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> type_pack </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span> T</span><span style=3D"color:rgb(102,102,0)">;=
</span></div>
</code></div><p>=A0</p><p>Usage example:</p><div style=3D"border:1px solid =
rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><c=
ode><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"colo=
r:rgb(102,102,0)">...</span><span> my_types </span><span style=3D"color:rgb=
(102,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,=
102,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </sp=
an><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb=
(102,102,0)">>;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span> my_tuple </spa=
n><span style=3D"color:rgb(102,102,0)">=3D</span><span> tuple</span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span>my_types</span><span style=
=3D"color:rgb(102,102,0)">...>;</span></div>
</code></div><p></p></div></blockquote><div><br></div></div><div>This immed=
iately creates a problem. One of the properties of packs today is that it i=
s possible to syntactically determine whether some snippet of C++ syntax co=
ntains unexpanded parameter packs, and to determine which packs it contains=
.. This is crucial to some implementation techniques.</div>
<div><br></div><div>It's also important in resolving some grammar ambig=
uities. Today, if I have:</div><div><br></div><div>=A0 template<typename=
T> void f(typename T::type x ...);<br></div><div><br></div><div>I know =
this is a vararg function. With your proposal, I could presumably write:</d=
iv>
<div><br></div><div>=A0 template<typename...Ts> struct X {</div><div>=
=A0 =A0 using ...type =3D Ts;</div><div>=A0 };</div><div>=A0 void g() {</di=
v><div>=A0 =A0 f<X<int, int, int>>(1, 2, 3);</div><div>=A0 }</d=
iv><div><br></div>
<div>and 'f' would mean something fundamentally different.</div><di=
v><br></div><div>I had a similar-but-different proposal a while back (which=
I've not written up for committee consideration yet) which avoids this=
problem by using a slightly different syntax:</div>
<div><br></div><div>=A0 template<typename...Ts> struct types {</div><=
div>=A0 =A0 using ... =3D Ts; // "...types<Ts>" is the pack=
"Ts"</div><div>=A0 };</div><div><br></div><div>=A0 typedef std::=
types<int, char, double> icd; // just a normal type</div>
<div>=A0 void f(...icd ...x) // "...icd" is a pack of types; this=
is "void f(int, char, double)" except that we have a pack of par=
ameters</div><div class=3D"im"><div><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div><font size=3D"4"><strong>Variable pack</strong></font=
></div><div>=A0</div><p>Variable packs are the same as function parameter p=
acks, except that they can be declared anywhere a variable can be declared.=
There are two ways to declare and initialize a variable pack.</p>
<p>The first one is by using an already defined type pack. If constructor a=
rguments are specified as single values, all the constructors of the variab=
les in the pack are called with those same arguments.</p><div style=3D"bord=
er:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250=
,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> types </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </sp=
an><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb=
(102,102,0)">>;</span><span><br>
types values1</span><span style=3D"color:rgb(102,102,0)">;</span></div></co=
de></div></div></blockquote><div><br></div></div><div>This syntax doesn'=
;t work. Consider:</div><div><br></div><div>=A0 template<typename ...Ts&=
gt;</div>
<div>=A0 void f(Ts ...ts) {</div><div>=A0 =A0 g(ts + []() {</div><div>=A0 =
=A0 =A0 types values;</div><div>=A0 =A0 =A0 return values;</div><div>=A0 =
=A0 }() ...);</div><div>=A0 }</div><div><br></div><div>This would be ambigu=
ous: does each lambda declare a *pack* of values, or a *slice* of that pack=
of values? The way to fix this is to consistently use pack expansion whene=
ver you expand a pack:</div>
<div><br></div><div>=A0 // assuming 'types' names a pack of types</=
div><div>=A0 types ...values1; // ok, declare a pack of values named 'v=
alues1'.</div><div><br></div><div>This would still be problematic if yo=
u allowed pack expansions as a static or non-static data member, because of=
the above-mentioned problem with being unable to syntactically determine w=
hat is and is not a pack.</div>
<div class=3D"im">
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px s=
olid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250=
)">
<code><div><span><br>type_pack</span><span style=3D"color:rgb(102,102,0)">&=
lt;</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D"color=
:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">c=
har</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span =
style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,102,=
0)">></span><span> values2</span><span style=3D"color:rgb(102,102,0)">;<=
/span><span><br>
types values3 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span> =
</span><span style=3D"color:rgb(0,102,102)">10</span><span style=3D"color:r=
gb(102,102,0)">;</span><span> </span><span style=3D"color:rgb(136,0,0)">// =
all 3 variables are initialized to 10</span><span><br>
types values4</span><span style=3D"color:rgb(102,102,0)">(</span><span styl=
e=3D"color:rgb(0,102,102)">10</span><span style=3D"color:rgb(102,102,0)">);=
</span><span> </span><span style=3D"color:rgb(136,0,0)">// same</span><span=
><br>
types values5 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span> =
values2</span><span style=3D"color:rgb(102,102,0)">;</span><span><br>type_p=
ack</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"co=
lor:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,102,0)">,</span=
><span> </span><span style=3D"color:rgb(0,0,136)">double</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">double</span><span style=3D"color:rgb(102,102,0)">></span><span>=
values6 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span> value=
s2</span><span style=3D"color:rgb(102,102,0)">;</span><span><br>
</span><span style=3D"color:rgb(136,0,0)">//type_pack<int, char> valu=
es7 =3D values2; //error: mismatching pack sizes</span><span><br><br></span=
><span style=3D"color:rgb(0,0,136)">template</span><span> </span><span styl=
e=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(102,102,0)">...</span><span> T</span><sp=
an style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">class</span><span> C<br></span><s=
pan style=3D"color:rgb(102,102,0)">{</span><span><br>=A0T</span><span style=
=3D"color:rgb(102,102,0)">...</span><span> values</span><span style=3D"colo=
r:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>This, for instanc=
e, is a problem, because X::values (for a dependent type X) might or might =
not be a pack if this were valid.</div><div class=3D"im"><div>=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span><br></span><=
span style=3D"color:rgb(102,102,0)">};</span><span><br><br></span><span sty=
le=3D"color:rgb(0,0,136)">template</span><span> </span><span style=3D"color=
:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span>=
<span style=3D"color:rgb(102,102,0)">...</span><span> T</span><span style=
=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">...</span><span> t</span><span style=3D"color:rgb(102,102,0)"=
>)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0T</span><s=
pan style=3D"color:rgb(102,102,0)">...</span><span> t2 </span><span style=
=3D"color:rgb(102,102,0)">=3D</span><span> t </span><span style=3D"color:rg=
b(102,102,0)">*</span><span> </span><span style=3D"color:rgb(0,102,102)">2<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><div=
>=A0</div><div>=A0</div><div>A variable pack can also be declared without a=
defined type pack. In that case, it must be initialized from another varia=
ble pack.</div>
<div>=A0</div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:bre=
ak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"color:=
rgb(136,0,0)">//double... values8; //error: unknown pack size</span><span><=
br>
</span><span style=3D"color:rgb(136,0,0)">//double... values9 =3D 10.0; //e=
rror: unknown pack size</span><span><br></span><span style=3D"color:rgb(0,0=
,136)">double</span><span style=3D"color:rgb(102,102,0)">...</span><span> v=
alues10 </span><span style=3D"color:rgb(102,102,0)">=3D</span><span> values=
2</span><span style=3D"color:rgb(102,102,0)">;</span><span> </span><span st=
yle=3D"color:rgb(136,0,0)">// pack of 3 variables of type double</span><spa=
n><br>
</span><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color=
:rgb(102,102,0)">...</span><span> values11</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span>values2</span><span style=3D"color:rgb(102,102,0)"=
>);</span><span> </span><span style=3D"color:rgb(136,0,0)">// same</span></=
div>
</code></div></div></blockquote><div><br></div></div><div>Seems fine to me:=
the pack expansion includes 'values2', so can infer its length fro=
m there.</div><div class=3D"im"><div>=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span><br></span><=
span style=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(102,1=
02,0)">...</span><span> values12 </span><span style=3D"color:rgb(102,102,0)=
">=3D</span><span> values2</span><span style=3D"color:rgb(102,102,0)">;</sp=
an><span> </span><span style=3D"color:rgb(136,0,0)">// pack of 3 variables =
of types int, char and double</span></div>
</code></div></div></blockquote><div><br></div></div><div>Presumably this m=
eans that your expansion model is that this expands to</div><div><br></div>=
<div><div>=A0 auto values12$0 =3D values2$0;</div><div>=A0 auto values12$1 =
=3D values2$1;</div>
<div>=A0 auto vaules12$2 =3D values2$2;</div></div><div><br></div><div>not =
the more natural choice of</div><div><br></div><div>=A0 auto values12$0 =3D=
values2$0, values12$1 =3D values2$1, vaules12$2 =3D values2$2;</div><div><=
br></div>
<div>(which would be ill-formed, because the 'auto' deduces to diff=
erent types in different deductions).</div><div class=3D"im"><div>=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span><br><br><br>=
</span><span style=3D"color:rgb(0,0,136)">template</span><span> </span><spa=
n style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,13=
6)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T</sp=
an><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">...</span><span> t</span><span style=3D"color:rgb(102,102,0)"=
>)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0</span><sp=
an style=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(102,102=
,0)">...</span><span> t2 </span><span style=3D"color:rgb(102,102,0)">=3D</s=
pan><span> t </span><span style=3D"color:rgb(102,102,0)">*</span><span> </s=
pan><span style=3D"color:rgb(0,102,102)">2</span><span style=3D"color:rgb(1=
02,102,0)">;</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><p><=
br>Operations can be done on packs if all the unexpanded packs are of the s=
ame size.</p><div style=3D"border:1px solid rgb(187,187,187);word-wrap:brea=
k-word;background-color:rgb(250,250,250)">
<code><div><span>values10 </span><span style=3D"color:rgb(102,102,0)">=3D</=
span><span> values11 </span><span style=3D"color:rgb(102,102,0)">*</span><s=
pan> </span><span style=3D"color:rgb(0,102,102)">2.0</span><span style=3D"c=
olor:rgb(102,102,0)">;</span><span><br>
values11 </span><span style=3D"color:rgb(102,102,0)">+=3D</span><span> valu=
es10</span><span style=3D"color:rgb(102,102,0)">;</span><span><br>values11 =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span> values10 </spa=
n><span style=3D"color:rgb(102,102,0)">+</span><span> values11</span><span =
style=3D"color:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this doesn=
't work, due to ambiguity over where the expansion happens. Instead, I&=
#39;d suggest (and indeed, have been intending to propose for standardizati=
on) adding an optional '...' before the ';' in an expressio=
n-statement, to represent a pack expansion. So you'd write:</div>
<div><br></div><div>=A0 values10 =3D values11 * 2.0 ...;</div><div><br></di=
v><div>and it would be equivalent to today's</div><div><br></div><div>=
=A0 sink{ values10 =3D values11 * 2.0 ... };</div><div>=A0</div><div>(for a=
n appropriately-defined class 'sink')</div>
<div class=3D"im">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p>Single values can be used along with p=
ack but only in operations in which those single values are const.<code></c=
ode></p>
<code><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><span style=3D"color:rgb(0,0,136)">doubl=
e</span><span> single_value </span><span style=3D"color:rgb(102,102,0)">=3D=
</span><span> </span><span style=3D"color:rgb(0,102,102)">1.0</span><span s=
tyle=3D"color:rgb(102,102,0)">;</span><span><br>
values10 </span><span style=3D"color:rgb(102,102,0)">*=3D</span><span> sing=
le_value</span><span style=3D"color:rgb(102,102,0)">;</span><span> </span><=
span style=3D"color:rgb(136,0,0)">//ok: rhs is const single_value</span><sp=
an><br>
single_value </span><span style=3D"color:rgb(102,102,0)">*=3D</span><span> =
values10</span><span style=3D"color:rgb(102,102,0)">;</span><span> </span><=
span style=3D"color:rgb(136,0,0)">//error: lhs of operator*=3D cannot be co=
nst</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">void</span><span> h</span><sp=
an style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)=
">const</span><span> </span><span style=3D"color:rgb(0,0,136)">double</span=
><span style=3D"color:rgb(102,102,0)">&,</span><span> </span><span styl=
e=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,102,0)">=
&)</span><span> </span><span style=3D"color:rgb(102,102,0)">{}</span><s=
pan><br>
<br>h</span><span style=3D"color:rgb(102,102,0)">(</span><span>values10</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span> values11</span><span=
style=3D"color:rgb(102,102,0)">);</span><span> </span><span style=3D"color=
:rgb(136,0,0)">//ok: 2 packs of the same size (h will be called 3 times)</s=
pan><span><br>
h</span><span style=3D"color:rgb(102,102,0)">(</span><span>single_value</sp=
an><span style=3D"color:rgb(102,102,0)">,</span><span> values10</span><span=
style=3D"color:rgb(102,102,0)">);</span><span> </span><span style=3D"color=
:rgb(136,0,0)">//ok: first arg of h is const (h will be called 3 times, eac=
h time with the same single_value)</span><span><br>
h</span><span style=3D"color:rgb(102,102,0)">(</span><span>values10</span><=
span style=3D"color:rgb(102,102,0)">,</span><span> single_value</span><span=
style=3D"color:rgb(102,102,0)">);</span><span> </span><span style=3D"color=
:rgb(136,0,0)">//error: trying to pass a non-const single value in an unexp=
anded context</span></div>
</code><p>=A0</p><p><font size=3D"4"><strong>Variable template pack</strong=
></font></p><p>Variable packs should also work for variable templates.</p><=
p>The most basic (and useful) variable template packs would be an equivalen=
t to std::integer_sequence that would allow working directly with an intege=
r pack (instead of having to store that pack in a type).</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span> </span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(0,0,136)">class</span><span> T</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> T</span><span style=3D"color:rgb(1=
02,102,0)">...</span><span> I</span><span style=3D"color:rgb(102,102,0)">&g=
t;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> T</span><s=
pan style=3D"color:rgb(102,102,0)">...</span><span> integer_pack </span><sp=
an style=3D"color:rgb(102,102,0)">=3D</span><span> I</span><span style=3D"c=
olor:rgb(102,102,0)">;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span>size_t</span><span st=
yle=3D"color:rgb(102,102,0)">...</span><span> I</span><span style=3D"color:=
rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> size_t</sp=
an><span style=3D"color:rgb(102,102,0)">...</span><span> index_pack </span>=
<span style=3D"color:rgb(102,102,0)">=3D</span><span> I</span><span style=
=3D"color:rgb(102,102,0)">;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span> T</span><span style=3D"color:rgb(102,102,0)">,</=
span><span> T N</span><span style=3D"color:rgb(102,102,0)">></span><span=
><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> T</span><s=
pan style=3D"color:rgb(102,102,0)">...</span><span> make_integer_pack </spa=
n><span style=3D"color:rgb(102,102,0)">=3D</span><span> integer_pack</span>=
<span style=3D"color:rgb(102,102,0)"><</span><span>T</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(13=
6,0,0)">/* a sequence 0, 1, 2, ..., N-1 */</span><span style=3D"color:rgb(1=
02,102,0)">>;</span></div>
</code></div></div></blockquote><div><br></div></div><div>My prior proposal=
had syntax for this sequence: ...N. This was also overloadable for user-de=
fined types, so that (for instance) for a tuple t, '...t' could be =
sugar for 'get<...N>(t)'.</div>
</div></div></div></blockquote><div><br></div><div>To save you the effort o=
f digging it up:</div><div><br></div><div><a href=3D"https://groups.google.=
com/a/isocpp.org/d/msg/std-proposals/g1HziHt1lbo/RHxb2fxKt5IJ">https://grou=
ps.google.com/a/isocpp.org/d/msg/std-proposals/g1HziHt1lbo/RHxb2fxKt5IJ</a>=
<br>
</div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);borde=
r-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_e=
xtra">
<div class=3D"gmail_quote"><div class=3D"im">
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px s=
olid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250=
)">
<code><div><span><br></span><span style=3D"color:rgb(0,0,136)">template</sp=
an><span> </span><span style=3D"color:rgb(102,102,0)"><</span><span>size=
_t N</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> size_t</sp=
an><span style=3D"color:rgb(102,102,0)">...</span><span> make_index_pack </=
span><span style=3D"color:rgb(102,102,0)">=3D</span><span> make_integer_pac=
k</span><span style=3D"color:rgb(102,102,0)"><</span><span>size_t</span>=
<span style=3D"color:rgb(102,102,0)">,</span><span> N</span><span style=3D"=
color:rgb(102,102,0)">>;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> size_t</sp=
an><span style=3D"color:rgb(102,102,0)">...</span><span> index_pack_for </s=
pan><span style=3D"color:rgb(102,102,0)">=3D</span><span> make_index_pack</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(0,0,136)">sizeof</span><span style=3D"color:rgb(102,102,0)">...(</span><=
span>T</span><span style=3D"color:rgb(102,102,0)">)>;</span></div>
</code></div><div>=A0</div><p>With these variable template packs, additiona=
l utilies can be provided for tuple-like classes:</p><div style=3D"border:1=
px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250=
,250)">
<code><div><span style=3D"color:rgb(136,0,0)">// tuple_indices<T> is =
equivalenent to 0, 1, ..., tuple_size<T>::value - 1</span><span><br><=
/span><span style=3D"color:rgb(0,0,136)">template</span><span> </span><span=
style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136=
)">class</span><span> T</span><span style=3D"color:rgb(102,102,0)">></sp=
an><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> size_t</sp=
an><span style=3D"color:rgb(102,102,0)">...</span><span> tuple_indices </sp=
an><span style=3D"color:rgb(102,102,0)">=3D</span><span> make_index_pack</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span>tuple_size</span>=
<span style=3D"color:rgb(102,102,0)"><</span><span>T</span><span style=
=3D"color:rgb(102,102,0)">>::</span><span>value</span><span style=3D"col=
or:rgb(102,102,0)">>;</span><span><br>
<br></span><span style=3D"color:rgb(136,0,0)">// tuple_elements<T> is=
equivalent to tuple_element_t<0, T>, tuple_element_t<1, T>, ..=
.., tuple_element_t<N-1, T></span><span><br></span><span style=3D"colo=
r:rgb(0,0,136)">template</span><span> </span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span><span> T</=
span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> tuple_elements </span><span style=3D"color=
:rgb(102,102,0)">=3D</span><span> tuple_element_t</span><span style=3D"colo=
r:rgb(102,102,0)"><</span><span>tuple_indices</span><span style=3D"color=
:rgb(102,102,0)"><</span><span>T</span><span style=3D"color:rgb(102,102,=
0)">>,</span><span> T</span><span style=3D"color:rgb(102,102,0)">>;</=
span></div>
</code></div><p><br>These are much more simpler to use than current workaro=
unds requiring usage of std::integer_sequence. Example of passing all eleme=
nts of tuple t as arguments to a function f:</p><div style=3D"border:1px so=
lid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)=
">
<code><div><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> <=
/span><span style=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:=
rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">=
Args</span><span style=3D"color:rgb(102,102,0)">&&...</span><span> =
args</span><span style=3D"color:rgb(102,102,0)">);</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span> </span><span style=3D"color:rgb(102,0,102)">Tupl=
e</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">&&</span><span> t</span><span style=3D"color:rgb(102,=
102,0)">)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0f</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">get</span><span style=3D"color:rgb(102,102,0)"><</span><span>tuple_in=
dices</span><span style=3D"color:rgb(102,102,0)"><</span><span>T</span><=
span style=3D"color:rgb(102,102,0)">>>(</span><span>forward</span><sp=
an style=3D"color:rgb(102,102,0)"><</span><span>T</span><span style=3D"c=
olor:rgb(102,102,0)">>(</span><span>t</span><span style=3D"color:rgb(102=
,102,0)">))...);</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div></di=
v></blockquote><div>=A0</div></div><div>This is still a little unclean. My =
proposal supports this as:</div><div><br></div><div>=A0 f(...std::forward&l=
t;T>(t) ...);</div>
<div class=3D"im">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p></p><p><strong><font size=3D"4">Return=
ing a pack from a function</font></strong></p>
<p>With pack variables comes the need for functions returning a pack of val=
ues.</p></div></blockquote><div><br></div></div><div>Why not return a tuple=
? Packs are not types, so functions returning packs doesn't really seem=
to make much sense.</div>
<div class=3D"im">
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><p>The most basic function =
that could be defined is one returning a pack from several values:</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">=
template</span><span> </span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(1=
02,102,0)">...</span><span> T</span><span style=3D"color:rgb(102,102,0)">&g=
t;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">decltype</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">auto</span><s=
pan style=3D"color:rgb(102,102,0)">)...</span><span> make_pack</span><span =
style=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:r=
gb(102,102,0)">&&...</span><span> t</span><span style=3D"color:rgb(=
102,102,0)">)</span><span> </span><span style=3D"color:rgb(102,102,0)">{</s=
pan><span> </span><span style=3D"color:rgb(0,0,136)">return</span><span> fo=
rward</span><span style=3D"color:rgb(102,102,0)"><</span><span>T</span><=
span style=3D"color:rgb(102,102,0)">>(</span><span>t</span><span style=
=3D"color:rgb(102,102,0)">);</span><span> </span><span style=3D"color:rgb(1=
02,102,0)">}</span></div>
</code></div><div>=A0</div><div>Usage example:</div><div>=A0</div><div styl=
e=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-colo=
r:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">void</spa=
n><span> g</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,136)">int</span><span> a</span><span style=3D"color:rgb(1=
02,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</sp=
an><span> b</span><span style=3D"color:rgb(102,102,0)">,</span><span> </spa=
n><span style=3D"color:rgb(0,0,136)">int</span><span> c</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">int</span><span> d</span><span style=3D"color:rgb(102,102,0)">,</sp=
an><span> </span><span style=3D"color:rgb(0,0,136)">int</span><span> e</spa=
n><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D=
"color:rgb(0,0,136)">int</span><span> f</span><span style=3D"color:rgb(102,=
102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span>=
<span> g</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><=
span style=3D"color:rgb(0,0,136)">int</span><span> h</span><span style=3D"c=
olor:rgb(102,102,0)">);</span><span><br>
<br></span><span style=3D"color:rgb(136,0,0)">// Following functions forwar=
d all arguments to g by first multiplying them by 2 and adding 3</span><spa=
n><br></span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,13=
6)">int</span><span> a</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> </span><span style=3D"color:rgb(0,0,136)">int</span><span> b</span><s=
pan style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"col=
or:rgb(0,0,136)">int</span><span> c</span><span style=3D"color:rgb(102,102,=
0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span><spa=
n> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span=
style=3D"color:rgb(0,0,136)">int</span><span> e</span><span style=3D"color=
:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">i=
nt</span><span> f</span><span style=3D"color:rgb(102,102,0)">,</span><span>=
</span><span style=3D"color:rgb(0,0,136)">int</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rg=
b(0,0,136)">int</span><span> h</span><span style=3D"color:rgb(102,102,0)">)=
</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0</span><sp=
an style=3D"color:rgb(136,0,0)">// Old way</span><span><br>=A0g</span><span=
style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"color:=
rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span>=
</span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span st=
yle=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,=
</span><span> b</span><span style=3D"color:rgb(102,102,0)">*</span><span st=
yle=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb=
(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</=
span><span style=3D"color:rgb(102,102,0)">,</span><span> c</span><span styl=
e=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</=
span><span> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </sp=
an><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span> d</span><span style=3D"color:rgb(102,102,0)">*</sp=
an><span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=
=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,=
102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</sp=
an><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,=
102,102)">2</span><span> </span><span style=3D"color:rgb(102,102,0)">+</spa=
n><span> </span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D=
"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"color:rgb(102,=
102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span> </span>=
<span style=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"c=
olor:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> g</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"c=
olor:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb(102,102=
,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</span><sp=
an style=3D"color:rgb(102,102,0)">,</span><span> h</span><span style=3D"col=
or:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><sp=
an> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span=
style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)=
">);</span><span><br>
=A0</span><span style=3D"color:rgb(136,0,0)">// New way</span><span><br>=A0=
g</span><span style=3D"color:rgb(102,102,0)">(</span><span>make_pack</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> b</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> c</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</span><=
span style=3D"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> g</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> h</span><span style=3D"color:rgb(102,102,0)">)*</span>=
<span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"c=
olor:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,1=
02)">3</span><span> </span><span style=3D"color:rgb(102,102,0)">...);</span=
></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this has t=
he problem of not syntactically identifying what's a pack and what'=
s not. With my syntax:</div><div><br></div><div>=A0 g(...tie(a, b, c, d, e,=
f, g, h)*2 + 3...);</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"h5"><di=
v style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgroun=
d-color:rgb(250,250,250)">
<code><div><span><br></span><span style=3D"color:rgb(102,102,0)">}</span></=
div></code></div><br><p>Another usage would be a function returning all the=
values of a tuple-like class:</p><p></p><div style=3D"border:1px solid rgb=
(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(136,0,0)">// get_all(t) is equivalent t=
o get<0>(t), get<1>(t), ..., get<N-1>(t)</span><span><br>=
</span><span style=3D"color:rgb(0,0,136)">template</span><span> </span><spa=
n style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,13=
6)">class</span><span> T</span><span style=3D"color:rgb(102,102,0)">></s=
pan><span><br>
</span><span style=3D"color:rgb(0,0,136)">constexpr</span><span> </span><sp=
an style=3D"color:rgb(0,0,136)">decltype</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,136)">auto</span><span style=
=3D"color:rgb(102,102,0)">)...</span><span> get_all</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rgb(102,102,=
0)">&&</span><span> t</span><span style=3D"color:rgb(102,102,0)">)<=
/span><span> </span><span style=3D"color:rgb(102,102,0)">{</span><span> </s=
pan><span style=3D"color:rgb(0,0,136)">return</span><span> </span><span sty=
le=3D"color:rgb(0,0,136)">get</span><span style=3D"color:rgb(102,102,0)">&l=
t;</span><span>tuple_indices</span><span style=3D"color:rgb(102,102,0)"><=
;</span><span>T</span><span style=3D"color:rgb(102,102,0)">>>(</span>=
<span>forward</span><span style=3D"color:rgb(102,102,0)"><</span><span>T=
</span><span style=3D"color:rgb(102,102,0)">>(</span><span>t</span><span=
style=3D"color:rgb(102,102,0)">));</span><span> </span><span style=3D"colo=
r:rgb(102,102,0)">}</span></div>
</code></div><br>Usage example (passing all elements of tuple t as argument=
s to a function f):<p></p><div style=3D"border:1px solid rgb(187,187,187);w=
ord-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span sty=
le=3D"color:rgb(0,0,136)">template</span><span> </span><span style=3D"color=
:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span>=
<span style=3D"color:rgb(102,102,0)">...</span><span> T</span><span style=
=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">&&...</span><span> t</span><span style=3D"color:rgb(1=
02,102,0)">);</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span> </span><span style=3D"color:rgb(102,0,102)">Tupl=
e</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">&&</span><span> t</span><span style=3D"color:rgb(102,=
102,0)">)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0f</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span>get_all</span><span style=
=3D"color:rgb(102,102,0)">(</span><span>forward</span><span style=3D"color:=
rgb(102,102,0)"><</span><span>T</span><span style=3D"color:rgb(102,102,0=
)">>(</span><span>t</span><span style=3D"color:rgb(102,102,0)">))...);</=
span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div><p>=
=A0</p><p><font size=3D"4"><strong>Expanding nested pack aliases</strong></=
font></p><p>Considering the following:</p><div style=3D"border:1px solid rg=
b(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> original </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(10=
2,102,0)"><</span><span>T0</span><span style=3D"color:rgb(102,102,0)">,<=
/span><span> T1</span><span style=3D"color:rgb(102,102,0)">,</span><span> <=
/span><span style=3D"color:rgb(136,0,0)">/*...*/</span><span style=3D"color=
:rgb(102,102,0)">,</span><span> TN</span><span style=3D"color:rgb(102,102,0=
)">>;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> </span><span style=3D"color:rgb(0,0,136)">=
alias</span><span> </span><span style=3D"color:rgb(102,102,0)">=3D</span><s=
pan> </span><span style=3D"color:rgb(136,0,0)">/*...*/</span><span style=3D=
"color:rgb(102,102,0)">;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> a </span><span style=3D"color:rgb(102,=
102,0)">=3D</span><span> </span><span style=3D"color:rgb(0,0,136)">alias</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span>original</span><s=
pan style=3D"color:rgb(102,102,0)">...>;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> b </span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span> </span><span style=3D"color:rgb(0,0,136)">alias</span>=
<span style=3D"color:rgb(0,136,0)"><original></span><span style=3D"co=
lor:rgb(102,102,0)">...;</span></div>
</code></div><p><br>The pack a is the result of applying the alias on the e=
ntire original pack.<br>The pack b is the result of applying the alias on e=
ach individual elements of the original pack.</p><p></p><div style=3D"borde=
r:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,=
250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> a </span><span style=3D"color:rgb(102,=
102,0)">=3D</span><span> </span><span style=3D"color:rgb(0,0,136)">alias</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span>T0</span><span st=
yle=3D"color:rgb(102,102,0)">,</span><span> T1</span><span style=3D"color:r=
gb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(136,0,0)">/*.=
...*/</span><span style=3D"color:rgb(102,102,0)">,</span><span> TN</span><sp=
an style=3D"color:rgb(102,102,0)">>;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> b </span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0)">&=
lt;</span><span style=3D"color:rgb(0,0,136)">alias</span><span style=3D"col=
or:rgb(102,102,0)"><</span><span>T0</span><span style=3D"color:rgb(102,1=
02,0)">>...,</span><span> </span><span style=3D"color:rgb(0,0,136)">alia=
s</span><span style=3D"color:rgb(102,102,0)"><</span><span>T1</span><spa=
n style=3D"color:rgb(102,102,0)">>...,</span><span> </span><span style=
=3D"color:rgb(136,0,0)">/*...*/</span><span style=3D"color:rgb(102,102,0)">=
,</span><span> </span><span style=3D"color:rgb(0,0,136)">alias</span><span =
style=3D"color:rgb(102,102,0)"><</span><span>TN</span><span style=3D"col=
or:rgb(102,102,0)">>...>;</span></div>
</code></div><br>When multiple aliases are used, the same rules can be appl=
ied successively by considering the inner-most pack first.<br>The following=
example illustrates how the rules are applied when 2 aliases are used on a=
pack.<p>
</p><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;ba=
ckground-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,13=
6)">using</span><span style=3D"color:rgb(102,102,0)">...</span><span> orig =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span> type_pack</spa=
n><span style=3D"color:rgb(102,102,0)"><</span><span>T0</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span> T1</span><span style=3D"color:rgb=
(102,102,0)">,</span><span> </span><span style=3D"color:rgb(136,0,0)">/*...=
*/</span><span style=3D"color:rgb(102,102,0)">,</span><span> TN</span><span=
style=3D"color:rgb(102,102,0)">>;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> a1 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> </span><span style=3D"color:rgb(136,0,0)">/*...*/</sp=
an><span style=3D"color:rgb(102,102,0)">;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> a2 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> </span><span style=3D"color:rgb(136,0,0)">/*...*/</sp=
an><span style=3D"color:rgb(102,102,0)">;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> a </span><span style=3D"color:rgb(102,=
102,0)">=3D</span><span> a1</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>a2</span><span style=3D"color:rgb(102,102,0)"><</span><span=
>orig</span><span style=3D"color:rgb(102,102,0)">...>...>;</span><spa=
n><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig...>;</span><span><br></span><span style=3D"color:rgb(136,0,0)">/=
/ =A0 =A0 =A0 =A0 =A0using... a =3D a1<temp...>;</span><span><br><br>=
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> b </span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span> a1</span><span style=3D"color:rgb(102,102,0)"><</sp=
an><span>a2</span><span style=3D"color:rgb(0,136,0)"><orig></span><sp=
an style=3D"color:rgb(102,102,0)">...</span><span> </span><span style=3D"co=
lor:rgb(102,102,0)">...>;</span><span><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig>...;</span><span><br></span><span style=3D"color:rgb(136,0,0)">/=
/ =A0 =A0 =A0 =A0 =A0using... b =3D a1<temp...>;</span><span><br><br>=
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> c </span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span> a1</span><span style=3D"color:rgb(102,102,0)"><</sp=
an><span>a2</span><span style=3D"color:rgb(102,102,0)"><</span><span>ori=
g</span><span style=3D"color:rgb(102,102,0)">...>>...;</span><span><b=
r>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig...>;</span><span><br></span><span style=3D"color:rgb(136,0,0)">/=
/ =A0 =A0 =A0 =A0 =A0using... c =3D a1<temp>...;</span><span><br><br>=
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> d </span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span> a1</span><span style=3D"color:rgb(102,102,0)"><</sp=
an><span>a2</span><span style=3D"color:rgb(0,136,0)"><orig></span><sp=
an style=3D"color:rgb(102,102,0)">...>...;</span><span><br>
</span><span style=3D"color:rgb(136,0,0)">// same as: using... temp =3D a2&=
lt;orig>...;</span><span><br></span><span style=3D"color:rgb(136,0,0)">/=
/ =A0 =A0 =A0 =A0 =A0using... d =3D a1<temp>...;</span><span><br><br>=
</span><span style=3D"color:rgb(136,0,0)">//using... e =3D a1<a2<orig=
>>... ...;</span><span><br>
</span><span style=3D"color:rgb(136,0,0)">// error</span><span><br><br></sp=
an><span style=3D"color:rgb(136,0,0)">//using... f =3D a1<a2<orig... =
....>>;</span><span><br></span><span style=3D"color:rgb(136,0,0)">// e=
rror</span></div>
</code></div><p><br>Additional examples</p></div></div><div style=3D"border=
:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,2=
50,250)"><code><div><div><div class=3D"h5"><span style=3D"color:rgb(0,0,136=
)">struct</span><span> A </span><span style=3D"color:rgb(102,102,0)">{};</s=
pan><span><br>
</span><span style=3D"color:rgb(0,0,136)">struct</span><span> B </span><spa=
n style=3D"color:rgb(102,102,0)">{};</span><span><br><br></span><span style=
=3D"color:rgb(0,0,136)">template</span><span> </span><span style=3D"color:r=
gb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span><s=
pan style=3D"color:rgb(102,102,0)">...</span><span> T</span><span style=3D"=
color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> twice </span><span style=3D"color:rgb(102,=
102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0=
)"><</span><span>T</span><span style=3D"color:rgb(102,102,0)">...,</span=
><span> T</span><span style=3D"color:rgb(102,102,0)">...>;</span><span><=
br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> AB </span><span style=3D"color:rgb(102=
,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,=
0)"><</span><span>A</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> B</span><span style=3D"color:rgb(102,102,0)">>;</span><span> =A0 =
=A0 =A0 =A0 =A0 =A0 </span><span style=3D"color:rgb(136,0,0)">// A, B</span=
><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t1 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>AB</span><span style=3D"color:rgb(102,102,0)">...>;</span><=
span> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, B, A, B</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t2 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0)">=
<</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span>AB</span><span style=3D"color:rgb(102,102,0)">...>...>;</span=
><span> =A0</span><span style=3D"color:rgb(136,0,0)">// A, B, A, B</span><s=
pan><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t3 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>AB</span><span style=3D"color:rgb(102,102,0)">>...;</span><=
span> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,=
0)">// A, A, B, B</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t4 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0)">=
<</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span>AB</span><span style=3D"color:rgb(102,102,0)">>...</span><span> =
</span><span style=3D"color:rgb(102,102,0)">...>;</span><span> </span><s=
pan style=3D"color:rgb(136,0,0)">// A, A, B, B</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t5 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>...>;</span><sp=
an> =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,0)">// A, B, A, B, A, =
B, A, B</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t6 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...</span><span> </sp=
an><span style=3D"color:rgb(102,102,0)">...>;</span><span> =A0 =A0 </spa=
n><span style=3D"color:rgb(136,0,0)">// A, A, B, B, A, A, B, B</span><span>=
<br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t7 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>>...;</span><sp=
an> =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,0)">// A, A, B, B, A, =
A, B, B</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> t8 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...>...;</span><sp=
an> =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,0)">// A, A, A, A, B, =
B, B, B</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">struct</span><span> C </span>=
<span style=3D"color:rgb(102,102,0)">{};</span><span><br><br></span><span s=
tyle=3D"color:rgb(0,0,136)">template</span><span> </span><span style=3D"col=
or:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</spa=
n><span style=3D"color:rgb(102,102,0)">...</span><span> T</span><span style=
=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> add_c </span><span style=3D"color:rgb(102,=
102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0=
)"><</span><span>T</span><span style=3D"color:rgb(102,102,0)">...,</span=
><span> C</span><span style=3D"color:rgb(102,102,0)">>;</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> u1 </span><span style=3D"color:rgb(102=
,102,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)">=
<</span><span>AB</span><span style=3D"color:rgb(102,102,0)">...>;</sp=
an><span> =A0 =A0 =A0 =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,0)">=
// A, B, C</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> u2 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>AB</span><span style=3D"color:rgb(102,102,0)">>...;</span><=
span> =A0 =A0 =A0 =A0 =A0 =A0</span><span style=3D"color:rgb(136,0,0)">// A=
, C, B, C</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> u3 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>...>;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, B, C, C</span><span>=
<br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> u4 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...</span><span> </sp=
an><span style=3D"color:rgb(102,102,0)">...>;</span><span> </span><span =
style=3D"color:rgb(136,0,0)">// A, C, B, C, C</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> u5 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>>...;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, C, B, C, C, C</span>=
<span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> u6 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...>...;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, C, C, C, B, C, C, C<=
/span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> v1 </span><span style=3D"color:rgb(102=
,102,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)">=
<</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span>AB</span><span style=3D"color:rgb(102,102,0)">...>...>;</span=
><span> =A0</span><span style=3D"color:rgb(136,0,0)">// A, B, A, B, C</span=
><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> v2 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...</span><span> </sp=
an><span style=3D"color:rgb(102,102,0)">...>;</span><span> </span><span =
style=3D"color:rgb(136,0,0)">// A, A, B, B, C</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> v3 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>twice</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>>...;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, C, B, C, A, C, B, C<=
/span><span><br>
</span></div></div><span style=3D"color:rgb(0,0,136)">using</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span> v4 </span><span style=3D"color=
:rgb(102,102,0)">=3D</span><span> add_c</span><span style=3D"color:rgb(102,=
102,0)"><</span><span>twice</span><span style=3D"color:rgb(102,102,0)">&=
lt;</span><span>AB</span><span style=3D"color:rgb(102,102,0)">>...>..=
..;</span><span> =A0</span><span style=3D"color:rgb(136,0,0)">// A, C, A, C,=
B, C, B, C</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> w1 </span><span style=3D"color:rgb(102=
,102,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)">=
<</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span>AB</span><span style=3D"color:rgb(102,102,0)">...>...>;</span=
><span> =A0</span><span style=3D"color:rgb(136,0,0)">// A, B, C, A, B, C</s=
pan><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> w2 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...</span><span> </sp=
an><span style=3D"color:rgb(102,102,0)">...>;</span><span> </span><span =
style=3D"color:rgb(136,0,0)">// A, C, B, C, A, C, B, C</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> w3 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">...>>...;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, A, B, B, C, C</span>=
<span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:=
rgb(102,102,0)">...</span><span> w4 </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span> twice</span><span style=3D"color:rgb(102,102,0)"><=
</span><span>add_c</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan>AB</span><span style=3D"color:rgb(102,102,0)">>...>...;</span><sp=
an> =A0</span><span style=3D"color:rgb(136,0,0)">// A, A, C, C, B, B, C, C<=
/span></div>
</code></div><span><font color=3D"#888888"><p>=A0</p></font></span><span cl=
ass=3D""><font color=3D"#888888"><p></p><p></p></font></span></div><span cl=
ass=3D""><font color=3D"#888888"><span><font color=3D"#888888">
<p></p>
-- <br>
=A0<br>
--- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br><br>
</font></span></font></span></blockquote></div></div></div>
</blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--20cf3079bfb8699c5704ebc9f944--
.
Author: Alex B <devalexb@gmail.com>
Date: Mon, 25 Nov 2013 10:41:33 -0500
Raw View
--001a11c3c704da404e04ec0232a7
Content-Type: text/plain; charset=ISO-8859-1
Hi Richard,
Thanks for you time; you bring a lot of good points. I just took a look at
the discussion you linked. I have to say that overloading operator... like
you propose is indeed really interesting. It is really neat and doesn't
have some of the issues introduced by my proposal. However, if I can manage
to solve those issues, I think (from my point of view) that my proposal
would provide a bit more power and fill more gaps in the language. See
below my answers to the issues you raised.
Usage example:
>> using... my_types = type_pack<int, char, double>;
>> using my_tuple = tuple<my_types...>;
>>
>>
> This immediately creates a problem. One of the properties of packs today
> is that it is possible to syntactically determine whether some snippet of
> C++ syntax contains unexpanded parameter packs, and to determine which
> packs it contains. This is crucial to some implementation techniques.
>
> It's also important in resolving some grammar ambiguities. Today, if I
> have:
>
> template<typename T> void f(typename T::type x ...);
>
> I know this is a vararg function. With your proposal, I could presumably
> write:
>
> template<typename...Ts> struct X {
> using ...type = Ts;
> };
> void g() {
> f<X<int, int, int>>(1, 2, 3);
> }
>
> and 'f' would mean something fundamentally different.
>
First, the ellipsis should go after the type name, not the var name. So
with my proposal, f would be declared like this:
template<typename T> void f(typename T::type... x);
Secondly, you are right that it remains ambiguous if T::type is a pack or
not. I guess a proper solution would be to have the "typename..." keyword
(used in the same context/fashion as regular "typename"). The example would
become:
template<typename T> void f(typename... T::type... x);
So first ellipsis (after typename) would indicate that what follows is a
pack (of types) and second ellipsis is for pack expansion.
Note that the same problem exists for a pack of values as you point out
later (see my answer to this).
> I had a similar-but-different proposal a while back (which I've not
> written up for committee consideration yet) which avoids this problem by
> using a slightly different syntax:
>
> template<typename...Ts> struct types {
> using ... = Ts; // "...types<Ts>" is the pack "Ts"
> };
>
> typedef std::types<int, char, double> icd; // just a normal type
> void f(...icd ...x) // "...icd" is a pack of types; this is "void f(int,
> char, double)" except that we have a pack of parameters
>
With my proposal you save the first ellipsis. It's no big deal, but sounds
cleaner to me to be able to define a pack alias directly than having to use
a wrapper type which has to be "unwrapped" every time.
using... types = type_pack<int, char, double>;
>> types values1;
>>
>
> This syntax doesn't work. Consider:
>
> template<typename ...Ts>
> void f(Ts ...ts) {
> g(ts + []() {
> types values;
> return values;
> }() ...);
> }
>
> This would be ambiguous: does each lambda declare a *pack* of values, or a
> *slice* of that pack of values? The way to fix this is to consistently use
> pack expansion whenever you expand a pack:
>
> // assuming 'types' names a pack of types
> types ...values1; // ok, declare a pack of values named 'values1'.
>
I think you are right. And it sounds consistent to me; that is how function
parameter packs are declared. Note taken.
template <class... T>
>> class C
>> {
>> T... values;
>>
>
> This, for instance, is a problem, because X::values (for a dependent type
> X) might or might not be a pack if this were valid.
>
Good point. Those would be ambiguous:
template <class T>
void f(T t)
{
using... icd = type_pack<int, char, double>;
icd... a = t.x; // member variable
icd... b = t.y(); // member function
icd... c = T::z; // static member variable
icd... d = T::w(); // static member function
}
Here it is ambiguous whether x, y, z and w are single values or packs of
values (note that there is no ambiguity for a non-template type T). To
disambiguate those cases, we could prefix with an ellipsis (indicating that
what follows is a pack):
icd... a = ... t.x;
icd... b = ... t.y();
icd... c = ... T::z;
icd... d = ... T::w();
This is similar to the "typename..." keyword but without the "typename"
since these are values.
Note that this would be in conflict with the operator... in your proposal.
It's a bit sad because I like your idea of overloading operator... and so
far it wasn't conflicting.
>> auto... values12 = values2; // pack of 3 variables of types int, char
>> and double
>>
>
> Presumably this means that your expansion model is that this expands to
>
> auto values12$0 = values2$0;
> auto values12$1 = values2$1;
> auto vaules12$2 = values2$2;
>
> not the more natural choice of
>
> auto values12$0 = values2$0, values12$1 = values2$1, vaules12$2 =
> values2$2;
>
> (which would be ill-formed, because the 'auto' deduces to different types
> in different deductions).
>
I didn't think about this. Indeed, as you say, for declaring packs it
sounds better to expand in the "less natural" way that you described (but I
don't like calling it less natural).
Operations can be done on packs if all the unexpanded packs are of the same
>> size.
>> values10 = values11 * 2.0;
>> values11 += values10;
>> values11 = values10 + values11;
>>
>
> Again, this doesn't work, due to ambiguity over where the expansion
> happens. Instead, I'd suggest (and indeed, have been intending to propose
> for standardization) adding an optional '...' before the ';' in an
> expression-statement, to represent a pack expansion. So you'd write:
>
> values10 = values11 * 2.0 ...;
>
That sounds like a good idea that would work with the current proposal.
I wonder if it would be required also when *declaring *:
1) auto... values12 = values2;
vs
2) auto... values12 = values2 ...;
Unless I'm wrong, (2) is invalid because the first ellipsis is already
expanding the pack.
template <class... Args>
>> void f(Args&&... args);
>>
>> template <class Tuple>
>> void g(T&& t)
>> {
>> f(get<tuple_indices<T>>(forward<T>(t))...);
>> }
>>
>
> This is still a little unclean. My proposal supports this as:
>
> f(...std::forward<T>(t) ...);
>
See my "cleaner" example a bit further:
f(get_all(forward<T>(t))...);
I've got to admit that in this case it's not as clean as your solution, but
still it's not that bad.
Change the global get_all by a member function and it also gets nicer:
f(forward<T>(t).all()...);
*Returning a pack from a function*
>>
>> With pack variables comes the need for functions returning a pack of
>> values.
>>
>
> Why not return a tuple? Packs are not types, so functions returning packs
> doesn't really seem to make much sense.
>
In your proposal, isn't the operator...() function returning a pack? It
looks like we have the same problem to solve.
So far I can think of two expansion models for returning packs. I'm not
sure which one is the best:
1- Calling a function returning a pack would in fact call several
functions, one for each pack element (so functions make_pack$0,
make_pack$1, etc would be called). The biggest problem with this approach
is that the code in the function is called several times... which might not
always be clear to the user. I think this approach is also considered in
the thread you linked where those issues are raised.
2- Have the language manage those multiple return values by itself. Maybe
internally the compiler can translate it to/from a tuple-like struct, with
a bit of "magic". But I'm not an expert in this area so couldn't say. It
might be a lot more trickier to implement (if possible at all) but would
lead to a much cleaner behavior from the user perspective.
> void g(int a, int b, int c, int d, int e, int f, int g, int h);
>>
>> // Following functions forward all arguments to g by first multiplying
>> them by 2 and adding 3
>> void f(int a, int b, int c, int d, int e, int f, int g, int h)
>> {
>> // Old way
>> g(a*2 + 3, b*2 + 3, c*2 + 3, d*2 + 3, e*2 + 3, f*2 + 3, g*2 + 3, h*2 + 3
>> );
>> // New way
>> g(make_pack(a, b, c, d, e, f, g, h)*2 + 3 ...);
>>
>
> Again, this has the problem of not syntactically identifying what's a pack
> and what's not. With my syntax:
>
> g(...tie(a, b, c, d, e, f, g, h)*2 + 3...);
>
Isn't the make_pack declaration explicit enough that what is returned by it
is a pack?
--
---
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/.
--001a11c3c704da404e04ec0232a7
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Richard,<div><br><div>Thanks for you time; you bring a =
lot of good points. I just took a look at the discussion you linked. I have=
to say that overloading operator... like you propose is indeed really inte=
resting. It is really neat and doesn't have some of the issues introduc=
ed by my proposal. However, if I can manage to solve those issues, I think =
(from my point of view) that my proposal would provide a bit more power and=
fill more gaps in the language. See below my answers to the issues you rai=
sed.</div>
<div><br></div><div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex">
<div dir=3D"ltr"><p>Usage example:</p><div style=3D"border:1px solid rgb(18=
7,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code><d=
iv><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:rgb(=
102,102,0)">...</span><span> my_types </span><span style=3D"color:rgb(102,1=
02,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0)=
"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D"co=
lor:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)=
">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><sp=
an style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,1=
02,0)">>;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span> my_tuple </spa=
n><span style=3D"color:rgb(102,102,0)">=3D</span><span> tuple</span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span>my_types</span><span style=
=3D"color:rgb(102,102,0)">...>;</span></div>
</code></div><p></p></div></blockquote><div><br></div></div><div>This immed=
iately creates a problem. One of the properties of packs today is that it i=
s possible to syntactically determine whether some snippet of C++ syntax co=
ntains unexpanded parameter packs, and to determine which packs it contains=
.. This is crucial to some implementation techniques.</div>
<div><br></div><div>It's also important in resolving some grammar ambig=
uities. Today, if I have:</div><div><br></div><div>=A0 template<typename=
T> void f(typename T::type x ...);<br></div><div><br></div><div>I know =
this is a vararg function. With your proposal, I could presumably write:</d=
iv>
<div><br></div><div>=A0 template<typename...Ts> struct X {</div><div>=
=A0 =A0 using ...type =3D Ts;</div><div>=A0 };</div><div>=A0 void g() {</di=
v><div>=A0 =A0 f<X<int, int, int>>(1, 2, 3);</div><div>=A0 }</d=
iv><div><br></div>
<div>and 'f' would mean something fundamentally different.</div></d=
iv></div></div></blockquote><div><br></div><div>First, the ellipsis should =
go after the type name, not the var name. So with my proposal, f would be d=
eclared like this:</div>
<div><br></div><div><div>=A0 =A0<font face=3D"courier new, monospace">templ=
ate<typename T> void f(typename T::type... x);</font><br></div></div>=
<div><br></div><div>Secondly, you are right that it remains ambiguous if T:=
:type is a pack or not. I guess a proper solution would be to have the &quo=
t;typename..." keyword (used in the same context/fashion as regular &q=
uot;typename"). The example would become:</div>
<div><br></div><div>=A0 =A0<font face=3D"courier new, monospace">template&l=
t;typename T> void f(typename... T::type... x);</font></div><div><br></d=
iv><div>So first ellipsis (after typename) would indicate that what follows=
is a pack (of types) and second ellipsis is for pack expansion.</div>
<div><br></div><div>Note that the same problem exists for a pack of values =
as you point out later (see my answer to this).</div><div><br></div><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style=
:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><br></div><div>I had a similar-but-different proposal a while back (which =
I've not written up for committee consideration yet) which avoids this =
problem by using a slightly different syntax:</div>
<div><br></div><div>=A0 template<typename...Ts> struct types {</div><=
div>=A0 =A0 using ... =3D Ts; // "...types<Ts>" is the pack=
"Ts"</div><div>=A0 };</div><div><br></div><div>=A0 typedef std::=
types<int, char, double> icd; // just a normal type</div>
<div>=A0 void f(...icd ...x) // "...icd" is a pack of types; this=
is "void f(int, char, double)" except that we have a pack of par=
ameters</div></div></div></div></blockquote><div><br></div><div>With my pro=
posal you save the first ellipsis. It's no big deal, but sounds cleaner=
to me to be able to define a pack alias directly than having to use a wrap=
per type which has to be "unwrapped" every time.</div>
<div><br></div><div><br></div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"=
gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> types </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </sp=
an><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb=
(102,102,0)">>;</span><span><br>
types values1</span><span style=3D"color:rgb(102,102,0)">;</span></div></co=
de></div></div></blockquote><div><br></div></div><div>This syntax doesn'=
;t work. Consider:</div><div><br></div><div>=A0 template<typename ...Ts&=
gt;</div>
<div>=A0 void f(Ts ...ts) {</div><div>=A0 =A0 g(ts + []() {</div><div>=A0 =
=A0 =A0 types values;</div><div>=A0 =A0 =A0 return values;</div><div>=A0 =
=A0 }() ...);</div><div>=A0 }</div><div><br></div><div>This would be ambigu=
ous: does each lambda declare a *pack* of values, or a *slice* of that pack=
of values? The way to fix this is to consistently use pack expansion whene=
ver you expand a pack:</div>
<div><br></div><div>=A0 // assuming 'types' names a pack of types</=
div><div>=A0 types ...values1; // ok, declare a pack of values named 'v=
alues1'.</div></div></div></div></blockquote><div><br></div><div>I thin=
k you are right. And it sounds consistent to me; that is how function param=
eter packs are declared. Note taken.</div>
<div><br></div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">class</span><span> C<br></span><s=
pan style=3D"color:rgb(102,102,0)">{</span><span><br>=A0T</span><span style=
=3D"color:rgb(102,102,0)">...</span><span> values</span><span style=3D"colo=
r:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>This, for instanc=
e, is a problem, because X::values (for a dependent type X) might or might =
not be a pack if this were valid.</div></div></div></div></blockquote>
<div><br></div><div>Good point. Those would be ambiguous:</div><div><br></d=
iv><div><div><font face=3D"courier new, monospace">=A0 =A0template <clas=
s T></font></div><div><font face=3D"courier new, monospace">=A0 =A0void =
f(T t)</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0{</font></div><div><font =
face=3D"courier new, monospace">=A0 =A0 =A0 using... icd =3D type_pack<i=
nt, char, double>;</font></div><div><font face=3D"courier new, monospace=
">=A0 =A0 =A0 icd... a =3D t.x; // member variable</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... b =3D t.y(); =
// member function</font></div><div><font face=3D"courier new, monospace">=
=A0 =A0 =A0 icd... c =3D T::z; // static member variable</font></div><div><=
font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D T::w(); // st=
atic member function</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0}</font></div><div><br></=
div><div>Here it is ambiguous whether x, y, z and w are single values or pa=
cks of values (note that there is no ambiguity for a non-template type T). =
To disambiguate those cases, we could prefix with an ellipsis (indicating t=
hat what follows is a pack):</div>
<div><br></div><div><div><font face=3D"courier new, monospace">=A0 =A0 =A0 =
icd... a =3D ... t.x;</font></div><div><font face=3D"courier new, monospace=
">=A0 =A0 =A0 icd... b =3D ... t.y();</font></div><div><font face=3D"courie=
r new, monospace">=A0 =A0 =A0 icd... c =3D ... T::z;</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D ... T::=
w();</font></div></div><div><br></div><div>This is similar to the "typ=
ename..." keyword but without the "typename" since these are=
values.</div>
<div><br></div><div>Note that this would be in conflict with the operator..=
.. in your proposal. It's a bit sad because I like your idea of overload=
ing operator... and so far it wasn't conflicting.</div></div><div><br>
</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_=
extra">
<div class=3D"gmail_quote"><div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div styl=
e=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-colo=
r:rgb(250,250,250)">
<code><div><span><br></span><span style=3D"color:rgb(0,0,136)">auto</span><=
span style=3D"color:rgb(102,102,0)">...</span><span> values12 </span><span =
style=3D"color:rgb(102,102,0)">=3D</span><span> values2</span><span style=
=3D"color:rgb(102,102,0)">;</span><span> </span><span style=3D"color:rgb(13=
6,0,0)">// pack of 3 variables of types int, char and double</span></div>
</code></div></div></blockquote><div><br></div></div><div>Presumably this m=
eans that your expansion model is that this expands to</div><div><br></div>=
<div><div>=A0 auto values12$0 =3D values2$0;</div><div>=A0 auto values12$1 =
=3D values2$1;</div>
<div>=A0 auto vaules12$2 =3D values2$2;</div></div><div><br></div><div>not =
the more natural choice of</div><div><br></div><div>=A0 auto values12$0 =3D=
values2$0, values12$1 =3D values2$1, vaules12$2 =3D values2$2;</div><div><=
br></div>
<div>(which would be ill-formed, because the 'auto' deduces to diff=
erent types in different deductions).</div></div></div></div></blockquote><=
div><br></div><div>I didn't think about this. Indeed, as you say, for d=
eclaring packs it sounds better to expand in the "less natural" w=
ay that you described (but I don't like calling it less natural).</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><p>Operations can be done on packs i=
f all the unexpanded packs are of the same size.</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)">
<code><div><span>values10 </span><span style=3D"color:rgb(102,102,0)">=3D</=
span><span> values11 </span><span style=3D"color:rgb(102,102,0)">*</span><s=
pan> </span><span style=3D"color:rgb(0,102,102)">2.0</span><span style=3D"c=
olor:rgb(102,102,0)">;</span><span><br>
values11 </span><span style=3D"color:rgb(102,102,0)">+=3D</span><span> valu=
es10</span><span style=3D"color:rgb(102,102,0)">;</span><span><br>values11 =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span> values10 </spa=
n><span style=3D"color:rgb(102,102,0)">+</span><span> values11</span><span =
style=3D"color:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this doesn=
't work, due to ambiguity over where the expansion happens. Instead, I&=
#39;d suggest (and indeed, have been intending to propose for standardizati=
on) adding an optional '...' before the ';' in an expressio=
n-statement, to represent a pack expansion. So you'd write:</div>
<div><br></div><div>=A0 values10 =3D values11 * 2.0 ...;</div></div></div><=
/div></blockquote><div><br></div><div>That sounds like a good idea that wou=
ld work with the current proposal.</div><div>I wonder if it would be requir=
ed also when <i>declaring </i>:</div>
<div><br></div><div><font face=3D"courier new, monospace">1) =A0auto... val=
ues12 =3D values2;</font></div><div>vs</div><div><div><font face=3D"courier=
new, monospace">2) =A0auto... values12 =3D values2 ...;</font></div></div>=
<div><br>
</div><div>Unless I'm wrong, (2) is invalid because the first ellipsis =
is already expanding the pack.</div><div><br></div><div><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-widt=
h:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-le=
ft:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"col=
or:rgb(0,0,136)">template</span><span> </span><span style=3D"color:rgb(102,=
102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span> </span><span style=3D"color:rg=
b(102,0,102)">Args</span><span style=3D"color:rgb(102,102,0)">></span><s=
pan><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">=
Args</span><span style=3D"color:rgb(102,102,0)">&&...</span><span> =
args</span><span style=3D"color:rgb(102,102,0)">);</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span> </span><span style=3D"color:rgb(102,0,102)">Tupl=
e</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">&&</span><span> t</span><span style=3D"color:rgb(102,=
102,0)">)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0f</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">get</span><span style=3D"color:rgb(102,102,0)"><</span><span>tuple_in=
dices</span><span style=3D"color:rgb(102,102,0)"><</span><span>T</span><=
span style=3D"color:rgb(102,102,0)">>>(</span><span>forward</span><sp=
an style=3D"color:rgb(102,102,0)"><</span><span>T</span><span style=3D"c=
olor:rgb(102,102,0)">>(</span><span>t</span><span style=3D"color:rgb(102=
,102,0)">))...);</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div></di=
v></blockquote><div>=A0</div></div><div>This is still a little unclean. My =
proposal supports this as:</div><div><br></div><div>=A0 f(...std::forward&l=
t;T>(t) ...);</div>
</div></div></div></blockquote><div><br></div><div>See my "cleaner&quo=
t; example a bit further:</div><div><span style=3D"color:rgb(80,0,80);font-=
family:monospace;background-color:rgb(250,250,250)">f</span><span style=3D"=
font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0=
)">(</span><span style=3D"color:rgb(80,0,80);font-family:monospace;backgrou=
nd-color:rgb(250,250,250)">get_all</span><span style=3D"font-family:monospa=
ce;background-color:rgb(250,250,250);color:rgb(102,102,0)">(</span><span st=
yle=3D"color:rgb(80,0,80);font-family:monospace;background-color:rgb(250,25=
0,250)">forward</span><span style=3D"font-family:monospace;background-color=
:rgb(250,250,250);color:rgb(102,102,0)"><</span><span style=3D"color:rgb=
(80,0,80);font-family:monospace;background-color:rgb(250,250,250)">T</span>=
<span style=3D"font-family:monospace;background-color:rgb(250,250,250);colo=
r:rgb(102,102,0)">>(</span><span style=3D"color:rgb(80,0,80);font-family=
:monospace;background-color:rgb(250,250,250)">t</span><span style=3D"font-f=
amily:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">)).=
...);</span><br>
</div><div><span style=3D"font-family:monospace;background-color:rgb(250,25=
0,250);color:rgb(102,102,0)"><br></span></div>I've got to admit that in=
this case it's not as clean as your solution, but still it's not t=
hat bad.</div>
<div class=3D"gmail_quote">Change the global get_all by a member function a=
nd it also gets nicer:</div><div class=3D"gmail_quote"><span style=3D"color=
:rgb(80,0,80);font-family:monospace;background-color:rgb(250,250,250)">f</s=
pan><span style=3D"font-family:monospace;background-color:rgb(250,250,250);=
color:rgb(102,102,0)">(</span><span style=3D"color:rgb(80,0,80);font-family=
:monospace;background-color:rgb(250,250,250)">forward</span><span style=3D"=
font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0=
)"><</span><span style=3D"color:rgb(80,0,80);font-family:monospace;backg=
round-color:rgb(250,250,250)">T</span><span style=3D"font-family:monospace;=
background-color:rgb(250,250,250);color:rgb(102,102,0)">>(</span><span s=
tyle=3D"color:rgb(80,0,80);font-family:monospace;background-color:rgb(250,2=
50,250)">t</span><span style=3D"font-family:monospace;background-color:rgb(=
250,250,250);color:rgb(102,102,0)">).all()...);</span><br>
</div><div class=3D"gmail_quote"><br><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div=
class=3D"gmail_extra">
<div class=3D"gmail_quote"><div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p></p><p><strong><font size=3D"4">Return=
ing a pack from a function</font></strong></p>
<p>With pack variables comes the need for functions returning a pack of val=
ues.</p></div></blockquote><div><br></div></div><div>Why not return a tuple=
? Packs are not types, so functions returning packs doesn't really seem=
to make much sense.</div>
</div></div></div></blockquote><div><br></div><div>In your proposal, isn=
9;t the operator...() function returning a pack? It looks like we have the =
same problem to solve.</div><div><br></div><div>So far I can think of two e=
xpansion models for returning packs. I'm not sure which one is the best=
:</div>
<div>1- Calling a function returning a pack would in fact call several func=
tions, one for each pack element (so functions make_pack$0, make_pack$1, et=
c would be called). The biggest problem with this approach is that the code=
in the function is called several times... which might not always be clear=
to the user. I think this approach is also considered in the thread you li=
nked where those issues are raised.</div>
<div>2- Have the language manage those multiple return values by itself. Ma=
ybe internally the compiler can translate it to/from a tuple-like struct, w=
ith a bit of "magic". But I'm not an expert in this area so c=
ouldn't say. It might be a lot more trickier to implement (if possible =
at all) but would lead to a much cleaner behavior from the user perspective=
..</div>
<div><br></div>
<div>=A0=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extr=
a"><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><sp=
an style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)=
">int</span><span> a</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an> </span><span style=3D"color:rgb(0,0,136)">int</span><span> b</span><spa=
n style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color=
:rgb(0,0,136)">int</span><span> c</span><span style=3D"color:rgb(102,102,0)=
">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span><span>=
d</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span s=
tyle=3D"color:rgb(0,0,136)">int</span><span> e</span><span style=3D"color:r=
gb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int=
</span><span> f</span><span style=3D"color:rgb(102,102,0)">,</span><span> <=
/span><span style=3D"color:rgb(0,0,136)">int</span><span> g</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(=
0,0,136)">int</span><span> h</span><span style=3D"color:rgb(102,102,0)">);<=
/span><span><br>
<br></span><span style=3D"color:rgb(136,0,0)">// Following functions forwar=
d all arguments to g by first multiplying them by 2 and adding 3</span><spa=
n><br></span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,13=
6)">int</span><span> a</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> </span><span style=3D"color:rgb(0,0,136)">int</span><span> b</span><s=
pan style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"col=
or:rgb(0,0,136)">int</span><span> c</span><span style=3D"color:rgb(102,102,=
0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span><spa=
n> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span=
style=3D"color:rgb(0,0,136)">int</span><span> e</span><span style=3D"color=
:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">i=
nt</span><span> f</span><span style=3D"color:rgb(102,102,0)">,</span><span>=
</span><span style=3D"color:rgb(0,0,136)">int</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rg=
b(0,0,136)">int</span><span> h</span><span style=3D"color:rgb(102,102,0)">)=
</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0</span><sp=
an style=3D"color:rgb(136,0,0)">// Old way</span><span><br>=A0g</span><span=
style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"color:=
rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span>=
</span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span st=
yle=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,=
</span><span> b</span><span style=3D"color:rgb(102,102,0)">*</span><span st=
yle=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb=
(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</=
span><span style=3D"color:rgb(102,102,0)">,</span><span> c</span><span styl=
e=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</=
span><span> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </sp=
an><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span> d</span><span style=3D"color:rgb(102,102,0)">*</sp=
an><span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=
=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,=
102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</sp=
an><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,=
102,102)">2</span><span> </span><span style=3D"color:rgb(102,102,0)">+</spa=
n><span> </span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D=
"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"color:rgb(102,=
102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span> </span>=
<span style=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"c=
olor:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> g</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"c=
olor:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb(102,102=
,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</span><sp=
an style=3D"color:rgb(102,102,0)">,</span><span> h</span><span style=3D"col=
or:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><sp=
an> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span=
style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)=
">);</span><span><br>
=A0</span><span style=3D"color:rgb(136,0,0)">// New way</span><span><br>=A0=
g</span><span style=3D"color:rgb(102,102,0)">(</span><span>make_pack</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> b</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> c</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</span><=
span style=3D"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> g</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> h</span><span style=3D"color:rgb(102,102,0)">)*</span>=
<span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"c=
olor:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,1=
02)">3</span><span> </span><span style=3D"color:rgb(102,102,0)">...);</span=
></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this has t=
he problem of not syntactically identifying what's a pack and what'=
s not. With my syntax:</div><div><br></div><div>=A0 g(...tie(a, b, c, d, e,=
f, g, h)*2 + 3...);</div>
</div></div></div></blockquote><div><br></div><div>Isn't the make_pack =
declaration explicit enough that what is returned by it is a pack?</div></d=
iv></div></div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3c704da404e04ec0232a7--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Mon, 25 Nov 2013 16:32:03 -0800
Raw View
--089e0111d9260cde0904ec099c16
Content-Type: text/plain; charset=ISO-8859-1
On Mon, Nov 25, 2013 at 7:41 AM, Alex B <devalexb@gmail.com> wrote:
> Hi Richard,
>
> Thanks for you time; you bring a lot of good points. I just took a look at
> the discussion you linked. I have to say that overloading operator... like
> you propose is indeed really interesting. It is really neat and doesn't
> have some of the issues introduced by my proposal. However, if I can manage
> to solve those issues, I think (from my point of view) that my proposal
> would provide a bit more power and fill more gaps in the language. See
> below my answers to the issues you raised.
>
> Usage example:
>>> using... my_types = type_pack<int, char, double>;
>>> using my_tuple = tuple<my_types...>;
>>>
>>>
>> This immediately creates a problem. One of the properties of packs today
>> is that it is possible to syntactically determine whether some snippet of
>> C++ syntax contains unexpanded parameter packs, and to determine which
>> packs it contains. This is crucial to some implementation techniques.
>>
>> It's also important in resolving some grammar ambiguities. Today, if I
>> have:
>>
>> template<typename T> void f(typename T::type x ...);
>>
>> I know this is a vararg function. With your proposal, I could presumably
>> write:
>>
>> template<typename...Ts> struct X {
>> using ...type = Ts;
>> };
>> void g() {
>> f<X<int, int, int>>(1, 2, 3);
>> }
>>
>> and 'f' would mean something fundamentally different.
>>
>
> First, the ellipsis should go after the type name, not the var name.
>
Sorry, the example I meant was
template<typename T> void f(typename T::type ...);
> So with my proposal, f would be declared like this:
>
> template<typename T> void f(typename T::type... x);
>
> Secondly, you are right that it remains ambiguous if T::type is a pack or
> not. I guess a proper solution would be to have the "typename..." keyword
> (used in the same context/fashion as regular "typename"). The example would
> become:
>
> template<typename T> void f(typename... T::type... x);
>
> So first ellipsis (after typename) would indicate that what follows is a
> pack (of types) and second ellipsis is for pack expansion.
>
> Note that the same problem exists for a pack of values as you point out
> later (see my answer to this).
>
I think it'd be unfortunate to need to introduce another disambiguation
syntax (in addition to 'template' and 'typename'). Since different elements
of a nested-name-specifier may or may not be packs, I think a better place
for the ... would be after a ::. So:
typename T::...U::type // T::U is a pack
typename T::U::...type // T::U::type is a pack
T::...value // T::value is a pack
I had a similar-but-different proposal a while back (which I've not written
>> up for committee consideration yet) which avoids this problem by using a
>> slightly different syntax:
>>
>> template<typename...Ts> struct types {
>> using ... = Ts; // "...types<Ts>" is the pack "Ts"
>> };
>>
>> typedef std::types<int, char, double> icd; // just a normal type
>> void f(...icd ...x) // "...icd" is a pack of types; this is "void
>> f(int, char, double)" except that we have a pack of parameters
>>
>
> With my proposal you save the first ellipsis. It's no big deal, but sounds
> cleaner to me to be able to define a pack alias directly than having to use
> a wrapper type which has to be "unwrapped" every time.
>
>
> using... types = type_pack<int, char, double>;
>>> types values1;
>>>
>>
>> This syntax doesn't work. Consider:
>>
>> template<typename ...Ts>
>> void f(Ts ...ts) {
>> g(ts + []() {
>> types values;
>> return values;
>> }() ...);
>> }
>>
>> This would be ambiguous: does each lambda declare a *pack* of values, or
>> a *slice* of that pack of values? The way to fix this is to consistently
>> use pack expansion whenever you expand a pack:
>>
>> // assuming 'types' names a pack of types
>> types ...values1; // ok, declare a pack of values named 'values1'.
>>
>
> I think you are right. And it sounds consistent to me; that is how
> function parameter packs are declared. Note taken.
>
>
> template <class... T>
>>> class C
>>> {
>>> T... values;
>>>
>>
>> This, for instance, is a problem, because X::values (for a dependent type
>> X) might or might not be a pack if this were valid.
>>
>
> Good point. Those would be ambiguous:
>
> template <class T>
> void f(T t)
> {
> using... icd = type_pack<int, char, double>;
> icd... a = t.x; // member variable
> icd... b = t.y(); // member function
> icd... c = T::z; // static member variable
> icd... d = T::w(); // static member function
> }
>
> Here it is ambiguous whether x, y, z and w are single values or packs of
> values (note that there is no ambiguity for a non-template type T). To
> disambiguate those cases, we could prefix with an ellipsis (indicating that
> what follows is a pack):
>
> icd... a = ... t.x;
> icd... b = ... t.y();
> icd... c = ... T::z;
> icd... d = ... T::w();
>
> This is similar to the "typename..." keyword but without the "typename"
> since these are values.
>
> Note that this would be in conflict with the operator... in your proposal.
> It's a bit sad because I like your idea of overloading operator... and so
> far it wasn't conflicting.
>
Examples like these are why I'm concerned about introducing first-class
packs in a broad set of contexts. (There seems to be very little advantage
in this over using std::tuple and the like, with an appropriate
'packification' operator.)
FWIW, there seems to be no problem with introducing packs at block scope
(local variable packs in particular), and I suspect that covers most of the
use cases.
>>> auto... values12 = values2; // pack of 3 variables of types int, char
>>> and double
>>>
>>
>> Presumably this means that your expansion model is that this expands to
>>
>> auto values12$0 = values2$0;
>> auto values12$1 = values2$1;
>> auto vaules12$2 = values2$2;
>>
>> not the more natural choice of
>>
>> auto values12$0 = values2$0, values12$1 = values2$1, vaules12$2 =
>> values2$2;
>>
>> (which would be ill-formed, because the 'auto' deduces to different types
>> in different deductions).
>>
>
> I didn't think about this. Indeed, as you say, for declaring packs it
> sounds better to expand in the "less natural" way that you described (but I
> don't like calling it less natural).
>
> Operations can be done on packs if all the unexpanded packs are of the
>>> same size.
>>> values10 = values11 * 2.0;
>>> values11 += values10;
>>> values11 = values10 + values11;
>>>
>>
>> Again, this doesn't work, due to ambiguity over where the expansion
>> happens. Instead, I'd suggest (and indeed, have been intending to propose
>> for standardization) adding an optional '...' before the ';' in an
>> expression-statement, to represent a pack expansion. So you'd write:
>>
>> values10 = values11 * 2.0 ...;
>>
>
> That sounds like a good idea that would work with the current proposal.
> I wonder if it would be required also when *declaring *:
>
> 1) auto... values12 = values2;
> vs
> 2) auto... values12 = values2 ...;
>
> Unless I'm wrong, (2) is invalid because the first ellipsis is already
> expanding the pack.
>
A single ellipsis here seems sufficient. The second one would presumably be
ill-formed.
template <class... Args>
>>> void f(Args&&... args);
>>>
>>> template <class Tuple>
>>> void g(T&& t)
>>> {
>>> f(get<tuple_indices<T>>(forward<T>(t))...);
>>> }
>>>
>>
>> This is still a little unclean. My proposal supports this as:
>>
>> f(...std::forward<T>(t) ...);
>>
>
> See my "cleaner" example a bit further:
> f(get_all(forward<T>(t))...);
>
> I've got to admit that in this case it's not as clean as your solution,
> but still it's not that bad.
> Change the global get_all by a member function and it also gets nicer:
> f(forward<T>(t).all()...);
>
> *Returning a pack from a function*
>>>
>>> With pack variables comes the need for functions returning a pack of
>>> values.
>>>
>>
>> Why not return a tuple? Packs are not types, so functions returning packs
>> doesn't really seem to make much sense.
>>
>
> In your proposal, isn't the operator...() function returning a pack? It
> looks like we have the same problem to solve.
>
operator... names a set of functions produced by pack expansion, and a
different function is used by each slice of the pack expansion (this is
your option (1) below).
> So far I can think of two expansion models for returning packs. I'm not
> sure which one is the best:
> 1- Calling a function returning a pack would in fact call several
> functions, one for each pack element (so functions make_pack$0,
> make_pack$1, etc would be called). The biggest problem with this approach
> is that the code in the function is called several times... which might not
> always be clear to the user. I think this approach is also considered in
> the thread you linked where those issues are raised.
> 2- Have the language manage those multiple return values by itself. Maybe
> internally the compiler can translate it to/from a tuple-like struct, with
> a bit of "magic". But I'm not an expert in this area so couldn't say. It
> might be a lot more trickier to implement (if possible at all) but would
> lead to a much cleaner behavior from the user perspective.
>
This second approach is very problematic, and actually doesn't really make
sense from the user's perspective, nor from the mechanical perspective of
pack expansion. Consider:
template<typename...T> using ...types = T;
types<int, char, double> f() { // return a pack
std::cout << "hello, world\n";
return {0, 0, 0};
}
template<typename...T> void g(T...);
template<typename...T> void h(T ...t) {
h(t ? f() : 0 ...);
}
void i() { h(true, false, true); }
How many times is f() called here? It seems "obvious" to me that it should
get called once per pack expansion, just like any other code within a pack
expansion, and the message should be printed out twice. It's not really
clear that it'd be possible to support this kind of construct with the
"language magic" in approach 2 (where the message would somehow be printed
out once?).
With f() returning a tuple, local variable packs, and explicit
packification, we get to write three different meaningful programs:
template<typename...T> void h1(T ...t) {
// call 'f()' once for each element of 't' that is true, and use the
corresponding element of f()'s result
h(t ? ...f() : 0 ...);
}
template<typename...T> void h2(T ...t) {
// call 'f()' three times, put each slice of 'f' into a local variable...
auto ...elems = ...f();
// ... and pass in the elements for which the corresponding element of
't' is true
h(t ? elems : 0 ...);
}
template<typename...T> void h3(T ...t) {
// call 'f()' once...
auto elems = f();
// ... and pass in the elements for which the corresponding element of
't' is true
h(t ? ...elems : 0 ...);
}
void g(int a, int b, int c, int d, int e, int f, int g, int h);
>>>
>>> // Following functions forward all arguments to g by first multiplying
>>> them by 2 and adding 3
>>> void f(int a, int b, int c, int d, int e, int f, int g, int h)
>>> {
>>> // Old way
>>> g(a*2 + 3, b*2 + 3, c*2 + 3, d*2 + 3, e*2 + 3, f*2 + 3, g*2 + 3, h*2 +
>>> 3);
>>> // New way
>>> g(make_pack(a, b, c, d, e, f, g, h)*2 + 3 ...);
>>>
>>
>> Again, this has the problem of not syntactically identifying what's a
>> pack and what's not. With my syntax:
>>
>> g(...tie(a, b, c, d, e, f, g, h)*2 + 3...);
>>
>
> Isn't the make_pack declaration explicit enough that what is returned by
> it is a pack?
>
That example would be fine, but if you put the same code inside a template,
it would be problematic.
--
---
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/.
--089e0111d9260cde0904ec099c16
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Nov 25, 2013 at 7:41 AM, Alex B <span dir=3D"ltr">=
<<a href=3D"mailto:devalexb@gmail.com" target=3D"_blank">devalexb@gmail.=
com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail=
_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style=
:solid;padding-left:1ex">
<div dir=3D"ltr">Hi Richard,<div><br><div>Thanks for you time; you bring a =
lot of good points. I just took a look at the discussion you linked. I have=
to say that overloading operator... like you propose is indeed really inte=
resting. It is really neat and doesn't have some of the issues introduc=
ed by my proposal. However, if I can manage to solve those issues, I think =
(from my point of view) that my proposal would provide a bit more power and=
fill more gaps in the language. See below my answers to the issues you rai=
sed.</div>
<div><br></div><div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><=
div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex">
<div dir=3D"ltr"><p>Usage example:</p><div style=3D"border:1px solid rgb(18=
7,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code><d=
iv><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"color:rgb(=
102,102,0)">...</span><span> my_types </span><span style=3D"color:rgb(102,1=
02,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,102,0)=
"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D"co=
lor:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)=
">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><sp=
an style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb(102,1=
02,0)">>;</span><span><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span> my_tuple </spa=
n><span style=3D"color:rgb(102,102,0)">=3D</span><span> tuple</span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span>my_types</span><span style=
=3D"color:rgb(102,102,0)">...>;</span></div>
</code></div><p></p></div></blockquote><div><br></div></div><div>This immed=
iately creates a problem. One of the properties of packs today is that it i=
s possible to syntactically determine whether some snippet of C++ syntax co=
ntains unexpanded parameter packs, and to determine which packs it contains=
.. This is crucial to some implementation techniques.</div>
<div><br></div><div>It's also important in resolving some grammar ambig=
uities. Today, if I have:</div><div><br></div><div>=A0 template<typename=
T> void f(typename T::type x ...);<br></div><div><br></div><div>I know =
this is a vararg function. With your proposal, I could presumably write:</d=
iv>
<div><br></div><div>=A0 template<typename...Ts> struct X {</div><div>=
=A0 =A0 using ...type =3D Ts;</div><div>=A0 };</div><div>=A0 void g() {</di=
v><div>=A0 =A0 f<X<int, int, int>>(1, 2, 3);</div><div>=A0 }</d=
iv><div><br></div>
<div>and 'f' would mean something fundamentally different.</div></d=
iv></div></div></blockquote><div><br></div></div><div>First, the ellipsis s=
hould go after the type name, not the var name.</div></div></div></div>
</div></div></blockquote><div><br></div><div>Sorry, the example I meant was=
<br></div><div><br></div><div>=A0 template<typename T> void f(typenam=
e T::type ...);</div><div>=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
> So with my proposal, f would be declared like this:</div>
<div><br></div><div><div>=A0 =A0<font face=3D"courier new, monospace">templ=
ate<typename T> void f(typename T::type... x);</font><br></div></div>=
<div><br></div><div>Secondly, you are right that it remains ambiguous if T:=
:type is a pack or not. I guess a proper solution would be to have the &quo=
t;typename..." keyword (used in the same context/fashion as regular &q=
uot;typename"). The example would become:</div>
<div><br></div><div>=A0 =A0<font face=3D"courier new, monospace">template&l=
t;typename T> void f(typename... T::type... x);</font></div><div><br></d=
iv><div>So first ellipsis (after typename) would indicate that what follows=
is a pack (of types) and second ellipsis is for pack expansion.</div>
<div><br></div><div>Note that the same problem exists for a pack of values =
as you point out later (see my answer to this).</div></div></div></div></bl=
ockquote><div><br></div><div>I think it'd be unfortunate to need to int=
roduce another disambiguation syntax (in addition to 'template' and=
'typename'). Since different elements of a nested-name-specifier m=
ay or may not be packs, I think a better place for the ... would be after a=
::. So:</div>
<div><br></div><div>=A0 typename T::...U::type // T::U is a pack</div><div>=
=A0 typename T::U::...type // T::U::type is a pack</div><div>=A0 T::...valu=
e // T::value is a pack</div><div><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>I had a similar-but-different proposal a while back (which I've not wr=
itten up for committee consideration yet) which avoids this problem by usin=
g a slightly different syntax:</div>
<div><br></div><div>=A0 template<typename...Ts> struct types {</div><=
div>=A0 =A0 using ... =3D Ts; // "...types<Ts>" is the pack=
"Ts"</div><div>=A0 };</div><div><br></div><div>=A0 typedef std::=
types<int, char, double> icd; // just a normal type</div>
<div>=A0 void f(...icd ...x) // "...icd" is a pack of types; this=
is "void f(int, char, double)" except that we have a pack of par=
ameters</div></div></div></div></blockquote><div><br></div></div><div>With =
my proposal you save the first ellipsis. It's no big deal, but sounds c=
leaner to me to be able to define a pack alias directly than having to use =
a wrapper type which has to be "unwrapped" every time.</div>
<div class=3D"im">
<div><br></div><div><br></div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"=
gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">using</span><span style=3D"co=
lor:rgb(102,102,0)">...</span><span> types </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span> type_pack</span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,=
0,136)">char</span><span style=3D"color:rgb(102,102,0)">,</span><span> </sp=
an><span style=3D"color:rgb(0,0,136)">double</span><span style=3D"color:rgb=
(102,102,0)">>;</span><span><br>
types values1</span><span style=3D"color:rgb(102,102,0)">;</span></div></co=
de></div></div></blockquote><div><br></div></div><div>This syntax doesn'=
;t work. Consider:</div><div><br></div><div>=A0 template<typename ...Ts&=
gt;</div>
<div>=A0 void f(Ts ...ts) {</div><div>=A0 =A0 g(ts + []() {</div><div>=A0 =
=A0 =A0 types values;</div><div>=A0 =A0 =A0 return values;</div><div>=A0 =
=A0 }() ...);</div><div>=A0 }</div><div><br></div><div>This would be ambigu=
ous: does each lambda declare a *pack* of values, or a *slice* of that pack=
of values? The way to fix this is to consistently use pack expansion whene=
ver you expand a pack:</div>
<div><br></div><div>=A0 // assuming 'types' names a pack of types</=
div><div>=A0 types ...values1; // ok, declare a pack of values named 'v=
alues1'.</div></div></div></div></blockquote><div><br></div></div><div>
I think you are right. And it sounds consistent to me; that is how function=
parameter packs are declared. Note taken.</div><div class=3D"im">
<div><br></div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span style=3D"color:rgb(102,102,0)">...</span><span> T=
</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">class</span><span> C<br></span><s=
pan style=3D"color:rgb(102,102,0)">{</span><span><br>=A0T</span><span style=
=3D"color:rgb(102,102,0)">...</span><span> values</span><span style=3D"colo=
r:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>This, for instanc=
e, is a problem, because X::values (for a dependent type X) might or might =
not be a pack if this were valid.</div></div></div></div></blockquote>
<div><br></div></div><div>Good point. Those would be ambiguous:</div><div><=
br></div><div><div><font face=3D"courier new, monospace">=A0 =A0template &l=
t;class T></font></div><div><font face=3D"courier new, monospace">=A0 =
=A0void f(T t)</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0{</font></div><div><font =
face=3D"courier new, monospace">=A0 =A0 =A0 using... icd =3D type_pack<i=
nt, char, double>;</font></div><div><font face=3D"courier new, monospace=
">=A0 =A0 =A0 icd... a =3D t.x; // member variable</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... b =3D t.y(); =
// member function</font></div><div><font face=3D"courier new, monospace">=
=A0 =A0 =A0 icd... c =3D T::z; // static member variable</font></div><div><=
font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D T::w(); // st=
atic member function</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0}</font></div><div><br></=
div><div>Here it is ambiguous whether x, y, z and w are single values or pa=
cks of values (note that there is no ambiguity for a non-template type T). =
To disambiguate those cases, we could prefix with an ellipsis (indicating t=
hat what follows is a pack):</div>
<div><br></div><div><div><font face=3D"courier new, monospace">=A0 =A0 =A0 =
icd... a =3D ... t.x;</font></div><div><font face=3D"courier new, monospace=
">=A0 =A0 =A0 icd... b =3D ... t.y();</font></div><div><font face=3D"courie=
r new, monospace">=A0 =A0 =A0 icd... c =3D ... T::z;</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D ... T::=
w();</font></div></div><div><br></div><div>This is similar to the "typ=
ename..." keyword but without the "typename" since these are=
values.</div>
<div><br></div><div>Note that this would be in conflict with the operator..=
.. in your proposal. It's a bit sad because I like your idea of overload=
ing operator... and so far it wasn't conflicting.</div></div></div>
</div></div></blockquote><div><br></div><div>Examples like these are why I&=
#39;m concerned about introducing first-class packs in a broad set of conte=
xts. (There seems to be very little advantage in this over using std::tuple=
and the like, with an appropriate 'packification' operator.)</div>
<div><br></div><div>FWIW, there seems to be no problem with introducing pac=
ks at block scope (local variable packs in particular), and I suspect that =
covers most of the use cases.</div><div><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra">
<div class=3D"gmail_quote"><div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div styl=
e=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-colo=
r:rgb(250,250,250)">
<code><div><span><br></span><span style=3D"color:rgb(0,0,136)">auto</span><=
span style=3D"color:rgb(102,102,0)">...</span><span> values12 </span><span =
style=3D"color:rgb(102,102,0)">=3D</span><span> values2</span><span style=
=3D"color:rgb(102,102,0)">;</span><span> </span><span style=3D"color:rgb(13=
6,0,0)">// pack of 3 variables of types int, char and double</span></div>
</code></div></div></blockquote><div><br></div></div><div>Presumably this m=
eans that your expansion model is that this expands to</div><div><br></div>=
<div><div>=A0 auto values12$0 =3D values2$0;</div><div>=A0 auto values12$1 =
=3D values2$1;</div>
<div>=A0 auto vaules12$2 =3D values2$2;</div></div><div><br></div><div>not =
the more natural choice of</div><div><br></div><div>=A0 auto values12$0 =3D=
values2$0, values12$1 =3D values2$1, vaules12$2 =3D values2$2;</div><div><=
br></div>
<div>(which would be ill-formed, because the 'auto' deduces to diff=
erent types in different deductions).</div></div></div></div></blockquote><=
div><br></div></div><div>I didn't think about this. Indeed, as you say,=
for declaring packs it sounds better to expand in the "less natural&q=
uot; way that you described (but I don't like calling it less natural).=
</div>
<div class=3D"im">
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><p>Operations can be done on packs i=
f all the unexpanded packs are of the same size.</p>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgr=
ound-color:rgb(250,250,250)">
<code><div><span>values10 </span><span style=3D"color:rgb(102,102,0)">=3D</=
span><span> values11 </span><span style=3D"color:rgb(102,102,0)">*</span><s=
pan> </span><span style=3D"color:rgb(0,102,102)">2.0</span><span style=3D"c=
olor:rgb(102,102,0)">;</span><span><br>
values11 </span><span style=3D"color:rgb(102,102,0)">+=3D</span><span> valu=
es10</span><span style=3D"color:rgb(102,102,0)">;</span><span><br>values11 =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span> values10 </spa=
n><span style=3D"color:rgb(102,102,0)">+</span><span> values11</span><span =
style=3D"color:rgb(102,102,0)">;</span></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this doesn=
't work, due to ambiguity over where the expansion happens. Instead, I&=
#39;d suggest (and indeed, have been intending to propose for standardizati=
on) adding an optional '...' before the ';' in an expressio=
n-statement, to represent a pack expansion. So you'd write:</div>
<div><br></div><div>=A0 values10 =3D values11 * 2.0 ...;</div></div></div><=
/div></blockquote><div><br></div></div><div>That sounds like a good idea th=
at would work with the current proposal.</div><div>I wonder if it would be =
required also when <i>declaring </i>:</div>
<div><br></div><div><font face=3D"courier new, monospace">1) =A0auto... val=
ues12 =3D values2;</font></div><div>vs</div><div><div><font face=3D"courier=
new, monospace">2) =A0auto... values12 =3D values2 ...;</font></div></div>=
<div><br>
</div><div>Unless I'm wrong, (2) is invalid because the first ellipsis =
is already expanding the pack.</div></div></div></div></blockquote><div><br=
></div><div>A single ellipsis here seems sufficient. The second one would p=
resumably be ill-formed.</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex">
<div dir=3D"ltr"><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"col=
or:rgb(0,0,136)">template</span><span> </span><span style=3D"color:rgb(102,=
102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span> </span><span style=3D"color:rg=
b(102,0,102)">Args</span><span style=3D"color:rgb(102,102,0)">></span><s=
pan><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">=
Args</span><span style=3D"color:rgb(102,102,0)">&&...</span><span> =
args</span><span style=3D"color:rgb(102,102,0)">);</span><span><br>
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span> </span>=
<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,=
0,136)">class</span><span> </span><span style=3D"color:rgb(102,0,102)">Tupl=
e</span><span style=3D"color:rgb(102,102,0)">></span><span><br>
</span><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span>T</span><span style=3D"color:rg=
b(102,102,0)">&&</span><span> t</span><span style=3D"color:rgb(102,=
102,0)">)</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0f</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136=
)">get</span><span style=3D"color:rgb(102,102,0)"><</span><span>tuple_in=
dices</span><span style=3D"color:rgb(102,102,0)"><</span><span>T</span><=
span style=3D"color:rgb(102,102,0)">>>(</span><span>forward</span><sp=
an style=3D"color:rgb(102,102,0)"><</span><span>T</span><span style=3D"c=
olor:rgb(102,102,0)">>(</span><span>t</span><span style=3D"color:rgb(102=
,102,0)">))...);</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">}</span></div></code></div></di=
v></blockquote><div>=A0</div></div><div>This is still a little unclean. My =
proposal supports this as:</div><div><br></div><div>=A0 f(...std::forward&l=
t;T>(t) ...);</div>
</div></div></div></blockquote><div><br></div></div><div>See my "clean=
er" example a bit further:</div><div><span style=3D"color:rgb(80,0,80)=
;font-family:monospace;background-color:rgb(250,250,250)">f</span><span sty=
le=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(80,0,80);font-family:monospace;ba=
ckground-color:rgb(250,250,250)">get_all</span><span style=3D"font-family:m=
onospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">(</span><s=
pan style=3D"color:rgb(80,0,80);font-family:monospace;background-color:rgb(=
250,250,250)">forward</span><span style=3D"font-family:monospace;background=
-color:rgb(250,250,250);color:rgb(102,102,0)"><</span><span style=3D"col=
or:rgb(80,0,80);font-family:monospace;background-color:rgb(250,250,250)">T<=
/span><span style=3D"font-family:monospace;background-color:rgb(250,250,250=
);color:rgb(102,102,0)">>(</span><span style=3D"color:rgb(80,0,80);font-=
family:monospace;background-color:rgb(250,250,250)">t</span><span style=3D"=
font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0=
)">))...);</span><br>
</div><div><span style=3D"font-family:monospace;background-color:rgb(250,25=
0,250);color:rgb(102,102,0)"><br></span></div>I've got to admit that in=
this case it's not as clean as your solution, but still it's not t=
hat bad.</div>
<div class=3D"gmail_quote">Change the global get_all by a member function a=
nd it also gets nicer:</div><div class=3D"gmail_quote"><span style=3D"color=
:rgb(80,0,80);font-family:monospace;background-color:rgb(250,250,250)">f</s=
pan><span style=3D"font-family:monospace;background-color:rgb(250,250,250);=
color:rgb(102,102,0)">(</span><span style=3D"color:rgb(80,0,80);font-family=
:monospace;background-color:rgb(250,250,250)">forward</span><span style=3D"=
font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0=
)"><</span><span style=3D"color:rgb(80,0,80);font-family:monospace;backg=
round-color:rgb(250,250,250)">T</span><span style=3D"font-family:monospace;=
background-color:rgb(250,250,250);color:rgb(102,102,0)">>(</span><span s=
tyle=3D"color:rgb(80,0,80);font-family:monospace;background-color:rgb(250,2=
50,250)">t</span><span style=3D"font-family:monospace;background-color:rgb(=
250,250,250);color:rgb(102,102,0)">).all()...);</span><br>
</div><div class=3D"gmail_quote"><div class=3D"im"><br><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><di=
v dir=3D"ltr">
<div class=3D"gmail_extra">
<div class=3D"gmail_quote"><div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><p></p><p><strong><font size=3D"4">Return=
ing a pack from a function</font></strong></p>
<p>With pack variables comes the need for functions returning a pack of val=
ues.</p></div></blockquote><div><br></div></div><div>Why not return a tuple=
? Packs are not types, so functions returning packs doesn't really seem=
to make much sense.</div>
</div></div></div></blockquote><div><br></div></div><div>In your proposal, =
isn't the operator...() function returning a pack? It looks like we hav=
e the same problem to solve.</div></div></div></div></blockquote><div>
<br></div><div>operator... names a set of functions produced by pack expans=
ion, and a different function is used by each slice of the pack expansion (=
this is your option (1) below).</div><div>=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>So far I can think of two expansion models for returning packs. I'm no=
t sure which one is the best:</div>
<div>1- Calling a function returning a pack would in fact call several func=
tions, one for each pack element (so functions make_pack$0, make_pack$1, et=
c would be called). The biggest problem with this approach is that the code=
in the function is called several times... which might not always be clear=
to the user. I think this approach is also considered in the thread you li=
nked where those issues are raised.</div>
<div>2- Have the language manage those multiple return values by itself. Ma=
ybe internally the compiler can translate it to/from a tuple-like struct, w=
ith a bit of "magic". But I'm not an expert in this area so c=
ouldn't say. It might be a lot more trickier to implement (if possible =
at all) but would lead to a much cleaner behavior from the user perspective=
..</div>
</div></div></div></blockquote><div><br></div><div>This second approach is =
very problematic, and actually doesn't really make sense from the user&=
#39;s perspective, nor from the mechanical perspective of pack expansion. C=
onsider:</div>
<div><br></div><div>template<typename...T> using ...types =3D T;</div=
><div>types<int, char, double> f() { // return a pack</div><div>=A0 s=
td::cout << "hello, world\n";</div><div>=A0 return {0, 0, 0=
};</div>
<div>}</div><div>template<typename...T> void g(T...);</div><div>templ=
ate<typename...T> void h(T ...t) {</div><div>=A0 h(t ? f() : 0 ...);<=
/div><div>}</div><div>void i() { h(true, false, true); }</div><div><br></di=
v>
<div>How many times is f() called here? It seems "obvious" to me =
that it should get called once per pack expansion, just like any other code=
within a pack expansion, and the message should be printed out twice. It&#=
39;s not really clear that it'd be possible to support this kind of con=
struct with the "language magic" in approach 2 (where the message=
would somehow be printed out once?).</div>
<div><br></div><div>With f() returning a tuple, local variable packs, and e=
xplicit packification, we get to write three different meaningful programs:=
</div><div><br></div><div><div>template<typename...T> void h1(T ...t)=
{</div>
<div>=A0 // call 'f()' once for each element of 't' that is=
true, and use the corresponding element of f()'s result</div><div>=A0 =
h(t ? ...f() : 0 ...);<br></div><div>}</div></div><div><div>template<typ=
ename...T> void h2(T ...t) {</div>
<div>=A0 // call 'f()' three times, put each slice of 'f' i=
nto a local variable...</div><div>=A0 auto ...elems =3D ...f();</div><div>=
=A0 // ... and pass in the elements for which the corresponding element of =
't' is true</div>
<div>=A0 h(t ? elems : 0 ...);</div><div>}</div></div><div><div><div>templa=
te<typename...T> void h3(T ...t) {</div><div>=A0 // call 'f()'=
; once...</div><div>=A0 auto elems =3D f();</div><div>=A0 // ... and pass i=
n the elements for which the corresponding element of 't' is true</=
div>
<div>=A0 h(t ? ...elems : 0 ...);</div><div>}</div></div></div><div><br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:soli=
d;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">
<div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">
<code><div><span style=3D"color:rgb(0,0,136)">void</span><span> g</span><sp=
an style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)=
">int</span><span> a</span><span style=3D"color:rgb(102,102,0)">,</span><sp=
an> </span><span style=3D"color:rgb(0,0,136)">int</span><span> b</span><spa=
n style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color=
:rgb(0,0,136)">int</span><span> c</span><span style=3D"color:rgb(102,102,0)=
">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span><span>=
d</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span s=
tyle=3D"color:rgb(0,0,136)">int</span><span> e</span><span style=3D"color:r=
gb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int=
</span><span> f</span><span style=3D"color:rgb(102,102,0)">,</span><span> <=
/span><span style=3D"color:rgb(0,0,136)">int</span><span> g</span><span sty=
le=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(=
0,0,136)">int</span><span> h</span><span style=3D"color:rgb(102,102,0)">);<=
/span><span><br>
<br></span><span style=3D"color:rgb(136,0,0)">// Following functions forwar=
d all arguments to g by first multiplying them by 2 and adding 3</span><spa=
n><br></span><span style=3D"color:rgb(0,0,136)">void</span><span> f</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,13=
6)">int</span><span> a</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> </span><span style=3D"color:rgb(0,0,136)">int</span><span> b</span><s=
pan style=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"col=
or:rgb(0,0,136)">int</span><span> c</span><span style=3D"color:rgb(102,102,=
0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">int</span><spa=
n> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> </span><span=
style=3D"color:rgb(0,0,136)">int</span><span> e</span><span style=3D"color=
:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rgb(0,0,136)">i=
nt</span><span> f</span><span style=3D"color:rgb(102,102,0)">,</span><span>=
</span><span style=3D"color:rgb(0,0,136)">int</span><span> g</span><span s=
tyle=3D"color:rgb(102,102,0)">,</span><span> </span><span style=3D"color:rg=
b(0,0,136)">int</span><span> h</span><span style=3D"color:rgb(102,102,0)">)=
</span><span><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span><br>=A0</span><sp=
an style=3D"color:rgb(136,0,0)">// Old way</span><span><br>=A0g</span><span=
style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"color:=
rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span>=
</span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span st=
yle=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,=
</span><span> b</span><span style=3D"color:rgb(102,102,0)">*</span><span st=
yle=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb=
(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</=
span><span style=3D"color:rgb(102,102,0)">,</span><span> c</span><span styl=
e=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</=
span><span> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </sp=
an><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span> d</span><span style=3D"color:rgb(102,102,0)">*</sp=
an><span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=
=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,=
102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</sp=
an><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,=
102,102)">2</span><span> </span><span style=3D"color:rgb(102,102,0)">+</spa=
n><span> </span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D=
"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"color:rgb(102,=
102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><span> </span>=
<span style=3D"color:rgb(102,102,0)">+</span><span> </span><span style=3D"c=
olor:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> g</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"c=
olor:rgb(0,102,102)">2</span><span> </span><span style=3D"color:rgb(102,102=
,0)">+</span><span> </span><span style=3D"color:rgb(0,102,102)">3</span><sp=
an style=3D"color:rgb(102,102,0)">,</span><span> h</span><span style=3D"col=
or:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,102,102)">2</span><sp=
an> </span><span style=3D"color:rgb(102,102,0)">+</span><span> </span><span=
style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(102,102,0)=
">);</span><span><br>
=A0</span><span style=3D"color:rgb(136,0,0)">// New way</span><span><br>=A0=
g</span><span style=3D"color:rgb(102,102,0)">(</span><span>make_pack</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span>a</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> b</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> c</span><span style=3D"color:rgb(102,102,0)">,</span><=
span> d</span><span style=3D"color:rgb(102,102,0)">,</span><span> e</span><=
span style=3D"color:rgb(102,102,0)">,</span><span> f</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span> g</span><span style=3D"color:rgb(102,10=
2,0)">,</span><span> h</span><span style=3D"color:rgb(102,102,0)">)*</span>=
<span style=3D"color:rgb(0,102,102)">2</span><span> </span><span style=3D"c=
olor:rgb(102,102,0)">+</span><span> </span><span style=3D"color:rgb(0,102,1=
02)">3</span><span> </span><span style=3D"color:rgb(102,102,0)">...);</span=
></div>
</code></div></div></blockquote><div><br></div></div><div>Again, this has t=
he problem of not syntactically identifying what's a pack and what'=
s not. With my syntax:</div><div><br></div><div>=A0 g(...tie(a, b, c, d, e,=
f, g, h)*2 + 3...);</div>
</div></div></div></blockquote><div><br></div></div><div>Isn't the make=
_pack declaration explicit enough that what is returned by it is a pack?</d=
iv></div></div></div></blockquote><div><br></div><div>That example would be=
fine, but if you put the same code inside a template, it would be problema=
tic.</div>
</div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0111d9260cde0904ec099c16--
.
Author: Alex B <devalexb@gmail.com>
Date: Tue, 26 Nov 2013 10:25:43 -0500
Raw View
--089e01176b29052fb004ec1618d3
Content-Type: text/plain; charset=ISO-8859-1
>
> Sorry, the example I meant was
>
> template<typename T> void f(typename T::type ...);
>
With the following syntax, there shouldn't be ambiguity:
template <typename T> void f(typename T::...type ...);
(similar to the following, which is not ambiguous:)
template <typename... T> void f(T ...);
> I think it'd be unfortunate to need to introduce another disambiguation
> syntax (in addition to 'template' and 'typename').
>
Well, that's what your proposal do (indirectly) as well. With your
proposal, you have to prefix with an ellipsis everywhere. With mine, you
only prefix with an ellipsis in ambiguous contexts.
To me, it sounds more consistent with actual syntax for declaring packs:
template <class... T>
void f(T... t) {}
In the function declaration, we don't need to prefix T with another
ellipsis to illustrate that it is a pack. In my proposal, it's the same
thing if T is an alias (except if it is an alias in a dependant name). In
your proposal, you always need to prefix T with an ellipsis if it is an
alias but never if it isn't. So to me, there is a tradeoff with both
approaches. In some cases your approach is more ellegant, but in some other
cases it is mine, like the following:
template <int First, int... Others>
class A
{
constexpr static int first = First;
// Your proposal:
constexpr static auto others = std::make_tuple(Others...);
constexpr static auto all = std::make_tuple(first, ...others...);
constexpr static auto all2 = std::make_tuple(...all * 2 ...);
// My proposal:
constexpr static int... others = Others;
constexpr static int... all = std::make_pack(first, others...);
constexpr static int... all2 = all * 2;
// Or if we do this in one line...
// Your proposal:
constexpr static auto all2 = std::make_tuple(...std::make_tuple(First,
Others...) * 2 ...);
// My proposal:
constexpr static int... all2 = std::make_pack(First, Others...) * 2;
};
Since different elements of a nested-name-specifier may or may not be
> packs, I think a better place for the ... would be after a ::. So:
>
> typename T::...U::type // T::U is a pack
> typename T::U::...type // T::U::type is a pack
> T::...value // T::value is a pack
>
That sounds better indeed.
Unfortunately, it gets a little dirtier when dealing with values:
icd... a = t. ...x;
icd... b = t. ...y();
icd... c = T::...z;
icd... d = T::...w();
That makes 4 dots in a row...
This second approach is very problematic, and actually doesn't really make
> sense from the user's perspective, nor from the mechanical perspective of
> pack expansion. Consider:
>
> template<typename...T> using ...types = T;
> types<int, char, double> f() { // return a pack
> std::cout << "hello, world\n";
> return {0, 0, 0};
> }
> template<typename...T> void g(T...);
> template<typename...T> void h(T ...t) {
> h(t ? f() : 0 ...);
> }
> void i() { h(true, false, true); }
>
> How many times is f() called here? It seems "obvious" to me that it should
> get called once per pack expansion, just like any other code within a pack
> expansion, and the message should be printed out twice. It's not really
> clear that it'd be possible to support this kind of construct with the
> "language magic" in approach 2 (where the message would somehow be printed
> out once?).
>
Your example is quite convincing.
> With f() returning a tuple, local variable packs, and explicit
> packification, we get to write three different meaningful programs:
>
> template<typename...T> void h1(T ...t) {
> // call 'f()' once for each element of 't' that is true, and use the
> corresponding element of f()'s result
> h(t ? ...f() : 0 ...);
> }
> template<typename...T> void h2(T ...t) {
> // call 'f()' three times, put each slice of 'f' into a local variable...
> auto ...elems = ...f();
> // ... and pass in the elements for which the corresponding element of
> 't' is true
> h(t ? elems : 0 ...);
> }
> template<typename...T> void h3(T ...t) {
> // call 'f()' once...
> auto elems = f();
> // ... and pass in the elements for which the corresponding element of
> 't' is true
> h(t ? ...elems : 0 ...);
> }
>
I'm a bit confused... are you mixing both our proposals in these examples?
What is the meaning of ... as a prefix in these examples? (is it the
meaning of my proposal or your proposal?)
Also, I'm not sure I understand that third example. What is the type of
elems?
I also have a question regarding your proposal. In the last part of my
original post, I proposed 2 different ways to expand a template pack alias.
It would allow the following (see my original post for more detailed
examples):
template <class... T>
using... twice = types<T..., T...>;
using... AB = types<A, B>;
using... ABAB = twice<AB...>; // A, B, A, B
using... AABB = twice<AB>...; // A, A, B, B
Would the last line be possible with your proposal?
template <class... T>
using twice = types<T..., T...>;
using AB = types<A, B>;
using ABAB = twice<...AB...>;
using AABB = ???;
--
---
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/.
--089e01176b29052fb004ec1618d3
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><div><span style=3D"color:rgb(34,34,34)">Sorry, the example I=
meant was</span><br></div></div><div><br></div><div>=A0 template<typena=
me T> void f(typename T::type ...);</div>
</div></div></div></blockquote><div><br></div><div>With the following synta=
x, there shouldn't be ambiguity:</div><div><br></div><div><font face=3D=
"courier new, monospace">template <typename T> void f(typename T::...=
type ...);</font></div>
<div><br></div><div>(similar to the following, which is not ambiguous:)</di=
v><div><br></div><div><font face=3D"courier new, monospace">template <ty=
pename... T> void f(T ...);</font></div><div><font face=3D"courier new, =
monospace"><br>
</font></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_extra">
<div class=3D"gmail_quote"><div class=3D"im"><div><span style=3D"color:rgb(=
34,34,34)">I think it'd be unfortunate to need to introduce another dis=
ambiguation syntax (in addition to 'template' and 'typename'=
;).</span><br>
</div></div></div></div></div></blockquote><div><br></div><div>Well, that&#=
39;s what your proposal do (indirectly) as well. With your proposal, you ha=
ve to prefix with an ellipsis everywhere. With mine, you only prefix with a=
n ellipsis in ambiguous contexts.</div>
<div><br></div><div>To me, it sounds more consistent with actual syntax for=
declaring packs:</div><div><br></div><div><font face=3D"courier new, monos=
pace">template <class... T></font></div><div><font face=3D"courier ne=
w, monospace">void f(T... t) {}</font></div>
<div><br></div><div>In the function declaration, we don't need to prefi=
x T with another ellipsis to illustrate that it is a pack. In my proposal, =
it's the same thing if T is an alias (except if it is an alias in a dep=
endant name). In your proposal, you always need to prefix T with an ellipsi=
s if it is an alias but never if it isn't. So to me, there is a tradeof=
f with both approaches. In some cases your approach is more ellegant, but i=
n some other cases it is mine, like the following:</div>
<div><br></div><div><div><font face=3D"courier new, monospace">template <=
;int First, int... Others></font></div><div><font face=3D"courier new, m=
onospace">class A</font></div><div><font face=3D"courier new, monospace">{<=
/font></div>
<div><font face=3D"courier new, monospace"><span class=3D"" style=3D"white-=
space:pre"> </span>constexpr static int first =3D First;</font></div><div><=
font face=3D"courier new, monospace"><br></font></div><div><font face=3D"co=
urier new, monospace"><span class=3D"" style=3D"white-space:pre"> </span>//=
Your proposal:</font></div>
<div><font face=3D"courier new, monospace"><span class=3D"" style=3D"white-=
space:pre"> </span>constexpr static auto others =3D std::make_tuple(Others.=
...);</font></div><div><font face=3D"courier new, monospace"><span class=3D"=
" style=3D"white-space:pre"> </span>constexpr static auto all =3D std::make=
_tuple(first, ...others...);</font></div>
<div><font face=3D"courier new, monospace"><span class=3D"" style=3D"white-=
space:pre"> </span>constexpr static auto all2 =3D std::make_tuple(...all * =
2 ...);</font></div><div><font face=3D"courier new, monospace"><br></font><=
/div><div>
<font face=3D"courier new, monospace"><span class=3D"" style=3D"white-space=
:pre"> </span>// My proposal:</font></div><div><font face=3D"courier new, m=
onospace"><span class=3D"" style=3D"white-space:pre"> </span>constexpr stat=
ic int... others =3D Others;</font></div>
<div><font face=3D"courier new, monospace"><span class=3D"" style=3D"white-=
space:pre"> </span>constexpr static int... all =3D std::make_pack(first, ot=
hers...);</font></div><div><font face=3D"courier new, monospace"><span clas=
s=3D"" style=3D"white-space:pre"> </span>constexpr static int... all2 =3D a=
ll * 2;</font></div>
<div><font face=3D"courier new, monospace"><div><br></div><div><span class=
=3D"" style=3D"white-space:pre"> </span>// Or if we do this in one line...<=
/div><div><br></div><div><span class=3D"" style=3D"white-space:pre"> </span=
>// Your proposal:</div>
<div><span class=3D"" style=3D"white-space:pre"> </span>constexpr static au=
to all2 =3D std::make_tuple(...std::make_tuple(First, Others...) * 2 ...);<=
/div><div><br></div><div><span class=3D"" style=3D"white-space:pre"> </span=
>// My proposal:</div>
<div><span class=3D"" style=3D"white-space:pre"> </span>constexpr static in=
t... all2 =3D std::make_pack(First, Others...) * 2;</div></font></div><div>=
<font face=3D"courier new, monospace">};</font></div></div><div><br></div><=
div>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<div> Since different elements of a nested-name-specifier may or may not be=
packs, I think a better place for the ... would be after a ::. So:</div>
<div><br></div><div>=A0 typename T::...U::type // T::U is a pack</div><div>=
=A0 typename T::U::...type // T::U::type is a pack</div><div>=A0 T::...valu=
e // T::value is a pack</div></div></div></div></blockquote><div><br></div>=
<div>
That sounds better indeed.</div><div><br></div><div>Unfortunately, it gets =
a little dirtier when dealing with values:</div><div><br></div><div><div st=
yle=3D"color:rgb(80,0,80)"><font face=3D"courier new, monospace">=A0 =A0 =
=A0 icd... a =3D t. ...x;</font></div>
<div style=3D"color:rgb(80,0,80)"><font face=3D"courier new, monospace">=A0=
=A0 =A0 icd... b =3D t. ...y();</font></div><div style=3D"color:rgb(80,0,8=
0)"><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... c =3D T::...z;=
</font></div><div style=3D"color:rgb(80,0,80)">
<font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D T::...w();</=
font></div></div><div><br></div><div>That makes 4 dots in a row...</div><di=
v><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><div><span style=3D"color:rgb(34,34,34)">This second approach=
is very problematic, and actually doesn't really make sense from the u=
ser's perspective, nor from the mechanical perspective of pack expansio=
n. Consider:</span><br>
</div></div>
<div><br></div><div>template<typename...T> using ...types =3D T;</div=
><div>types<int, char, double> f() { // return a pack</div><div>=A0 s=
td::cout << "hello, world\n";</div><div>=A0 return {0, 0, 0=
};</div>
<div>}</div><div>template<typename...T> void g(T...);</div><div>templ=
ate<typename...T> void h(T ...t) {</div><div>=A0 h(t ? f() : 0 ...);<=
/div><div>}</div><div>void i() { h(true, false, true); }</div><div><br></di=
v>
<div>How many times is f() called here? It seems "obvious" to me =
that it should get called once per pack expansion, just like any other code=
within a pack expansion, and the message should be printed out twice. It&#=
39;s not really clear that it'd be possible to support this kind of con=
struct with the "language magic" in approach 2 (where the message=
would somehow be printed out once?).</div>
</div></div></div></blockquote><div><br></div><div>Your example is quite co=
nvincing.</div><div><br></div><div>=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">
<div>With f() returning a tuple, local variable packs, and explicit packifi=
cation, we get to write three different meaningful programs:<br></div><div>=
<br></div><div><div>template<typename...T> void h1(T ...t) {</div>
<div>=A0 // call 'f()' once for each element of 't' that is=
true, and use the corresponding element of f()'s result</div><div>=A0 =
h(t ? ...f() : 0 ...);<br></div><div>}</div></div><div><div>template<typ=
ename...T> void h2(T ...t) {</div>
<div>=A0 // call 'f()' three times, put each slice of 'f' i=
nto a local variable...</div><div>=A0 auto ...elems =3D ...f();</div><div>=
=A0 // ... and pass in the elements for which the corresponding element of =
't' is true</div>
<div>=A0 h(t ? elems : 0 ...);</div><div>}</div></div><div><div><div>templa=
te<typename...T> void h3(T ...t) {</div><div>=A0 // call 'f()'=
; once...</div><div>=A0 auto elems =3D f();</div><div>=A0 // ... and pass i=
n the elements for which the corresponding element of 't' is true</=
div>
<div>=A0 h(t ? ...elems : 0 ...);</div><div>}</div></div></div></div></div>=
</div></blockquote><div><br></div><div>I'm a bit confused... are you mi=
xing both our proposals in these examples? What is the meaning of ... as a =
=A0prefix in these examples? (is it the meaning of my proposal or your prop=
osal?)</div>
<div>Also, I'm not sure I understand that third example. What is the ty=
pe of elems?</div><div><br></div><div><br></div><div><br></div><div>I also =
have a question regarding your proposal. In the last part of my original po=
st, I proposed 2 different ways to expand a template pack alias. It would a=
llow the following (see my original post for more detailed examples):</div>
<div><br></div></div></div><blockquote style=3D"margin:0 0 0 40px;border:no=
ne;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>=
<div><font face=3D"courier new, monospace">template <class... T></fon=
t></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><div><font face=3D"courier new, monospace">using... twice =3D types<T.=
..., T...>;</font></div></div></div></div><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<div><div><font face=3D"courier new, monospace"><br></font></div></div></di=
v></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><div><fo=
nt face=3D"courier new, monospace">using... AB =3D types<A, B>;</font=
></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><div><font face=3D"courier new, monospace">using... ABAB =3D twice<AB.=
...>; // A, B, A, B</font></div></div></div></div><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote">
<div><div><font face=3D"courier new, monospace">using... AABB =3D twice<=
AB>...; // A, A, B, B</font></div></div></div></div></blockquote><div cl=
ass=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></div><div>Would th=
e last line be possible with your proposal?</div>
<div><br></div></div></div><blockquote style=3D"margin:0 0 0 40px;border:no=
ne;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>=
<div><font face=3D"courier new, monospace">template <class... T></fon=
t></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><font face=3D"courier new, monospace">using twice =3D types<T..., T...=
>;</font></div></div></div><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote">
<div><font face=3D"courier new, monospace"><br></font></div></div></div><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"couri=
er new, monospace">using AB =3D types<A, B>;</font></div></div></div>=
<div class=3D"gmail_extra">
<div class=3D"gmail_quote"><div><font face=3D"courier new, monospace">using=
ABAB =3D twice<...AB...>;</font></div></div></div><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div><font face=3D"courier new, monospa=
ce">using AABB =3D ???;</font></div>
</div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01176b29052fb004ec1618d3--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 26 Nov 2013 07:55:59 -0800
Raw View
On ter=E7a-feira, 26 de novembro de 2013 10:25:43, Alex B wrote:
> // My proposal:
> constexpr static int... others =3D Others;
> constexpr static int... all =3D std::make_pack(first, others...);
> constexpr static int... all2 =3D all * 2;
What type is int... in memory?
That sounds awfully like an array. You can write:
constexpr static int others[] =3D { Others... };
constexpr static int all[] =3D std::make_pack(first, others...);
constexpr static int all2[] =3D { (Others * 2)... };
Accessing all from all2 requires something that makes an index list so you =
can=20
write all[make_index<Others>::value]...
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Alex B <devalexb@gmail.com>
Date: Tue, 26 Nov 2013 11:23:15 -0500
Raw View
--001a11343296d1fbc804ec16e58f
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Yes, in memory it is similar to an array.
constexpr static int... others =3D Others;
Translates to
constexpr static int others$0 =3D Others$0;
constexpr static int others$1 =3D Others$1;
[...]
Of course a pack of integers can be stored in an array. But then you can't
expand the array like you expand a pack.
The goal is to be able to store *and *reuse (expand) a pack in other
contexts. In this example I was only showing how to store a pack but didn't
really reuse/expand it in other contexts (except for all2 being defined
from all).
On Tue, Nov 26, 2013 at 10:55 AM, Thiago Macieira <thiago@macieira.org>wrot=
e:
> On ter=E7a-feira, 26 de novembro de 2013 10:25:43, Alex B wrote:
> > // My proposal:
> > constexpr static int... others =3D Others;
> > constexpr static int... all =3D std::make_pack(first, others...);
> > constexpr static int... all2 =3D all * 2;
>
> What type is int... in memory?
>
> That sounds awfully like an array. You can write:
>
> constexpr static int others[] =3D { Others... };
> constexpr static int all[] =3D std::make_pack(first, others...);
> constexpr static int all2[] =3D { (Others * 2)... };
>
> Accessing all from all2 requires something that makes an index list so yo=
u
> can
> write all[make_index<Others>::value]...
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11343296d1fbc804ec16e58f
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Yes, in memory it is similar to an array.</div><div><=
br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><d=
iv><font face=3D"courier new, monospace">constexpr static int... others =3D=
Others;</font></div>
</blockquote><div><br></div><div>Translates to</div><blockquote style=3D"ma=
rgin:0 0 0 40px;border:none;padding:0px"><div><font face=3D"courier new, mo=
nospace">constexpr static int others$0 =3D Others$0;</font></div><div><font=
face=3D"courier new, monospace">constexpr static int others$1 =3D Others$1=
;</font></div>
</blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px=
"><div>[...]</div></blockquote><div><br></div>Of course a pack of integers =
can be stored in an array. But then you can't expand the array like you=
expand a pack.<div>
<br></div><div>The goal is to be able to store <b>and </b>reuse (expand) a =
pack in other contexts. In this example I was only showing how to store a p=
ack but didn't really reuse/expand it in other contexts (except for all=
2 being defined from all).</div>
<div><br></div></div><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Tue, Nov 26, 2013 at 10:55 AM, Thiago Macieira <span dir=3D"ltr"=
><<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">thiago@maciei=
ra.org</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im">On ter=E7a-feira, 26 de no=
vembro de 2013 10:25:43, Alex B wrote:<br>
> // My proposal:<br>
> constexpr static int... others =3D Others;<br>
> constexpr static int... all =3D std::make_pack(first, others...);<br>
> constexpr static int... all2 =3D all * 2;<br>
<br>
</div>What type is int... in memory?<br>
<br>
That sounds awfully like an array. You can write:<br>
<br>
=A0 =A0constexpr static int others[] =3D { Others... };<br>
=A0 =A0constexpr static int all[] =3D std::make_pack(first, others...);<br>
=A0 =A0constexpr static int all2[] =3D { (Others * 2)... };<br>
<br>
Accessing all from all2 requires something that makes an index list so you =
can<br>
write all[make_index<Others>::value]...<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
--<br>
Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=3D"_b=
lank">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank">kde.org</a><br>
=A0 =A0Software Architect - Intel Open Source Technology Center<br>
=A0 =A0 =A0 PGP/GPG: 0x6EF45358; fingerprint:<br>
=A0 =A0 =A0 E067 918B B660 DBD1 105C =A0966C 33F5 F005 6EF4 5358<br>
</font></span><div class=3D"HOEnZb"><div class=3D"h5"><br>
--<br>
<br>
---<br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ=
/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscrib=
e@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11343296d1fbc804ec16e58f--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Tue, 26 Nov 2013 12:58:49 -0800
Raw View
--089e0160c2dc4cef6704ec1abfee
Content-Type: text/plain; charset=ISO-8859-1
On Tue, Nov 26, 2013 at 7:25 AM, Alex B <devalexb@gmail.com> wrote:
> Sorry, the example I meant was
>>
>> template<typename T> void f(typename T::type ...);
>>
>
> With the following syntax, there shouldn't be ambiguity:
>
> template <typename T> void f(typename T::...type ...);
>
> (similar to the following, which is not ambiguous:)
>
> template <typename... T> void f(T ...);
>
>
>
>> I think it'd be unfortunate to need to introduce another disambiguation
>> syntax (in addition to 'template' and 'typename').
>>
>
> Well, that's what your proposal do (indirectly) as well. With your
> proposal, you have to prefix with an ellipsis everywhere. With mine, you
> only prefix with an ellipsis in ambiguous contexts.
>
I don't see it that way. In my proposal, x and ...x are distinct things,
and both are meaningful and useful. You only use the ... operator when you
are converting a non-pack into a pack -- it's *not* performing
disambiguation, it's performing a conversion to a different kind of entity.
To me, it sounds more consistent with actual syntax for declaring packs:
>
> template <class... T>
> void f(T... t) {}
>
> In the function declaration, we don't need to prefix T with another
> ellipsis to illustrate that it is a pack. In my proposal, it's the same
> thing if T is an alias (except if it is an alias in a dependant name). In
> your proposal, you always need to prefix T with an ellipsis if it is an
> alias but never if it isn't. So to me, there is a tradeoff with both
> approaches. In some cases your approach is more ellegant, but in some other
> cases it is mine, like the following:
>
> template <int First, int... Others>
> class A
> {
> constexpr static int first = First;
>
> // Your proposal:
> constexpr static auto others = std::make_tuple(Others...);
> constexpr static auto all = std::make_tuple(first, ...others...);
> constexpr static auto all2 = std::make_tuple(...all * 2 ...);
>
> // My proposal:
> constexpr static int... others = Others;
> constexpr static int... all = std::make_pack(first, others...);
> constexpr static int... all2 = all * 2;
>
> // Or if we do this in one line...
>
> // Your proposal:
> constexpr static auto all2 = std::make_tuple(...std::make_tuple(First,
> Others...) * 2 ...);
>
> // My proposal:
> constexpr static int... all2 = std::make_pack(First, Others...) * 2;
> };
>
>
> Since different elements of a nested-name-specifier may or may not be
>> packs, I think a better place for the ... would be after a ::. So:
>>
>> typename T::...U::type // T::U is a pack
>> typename T::U::...type // T::U::type is a pack
>> T::...value // T::value is a pack
>>
>
> That sounds better indeed.
>
> Unfortunately, it gets a little dirtier when dealing with values:
>
> icd... a = t. ...x;
> icd... b = t. ...y();
> icd... c = T::...z;
> icd... d = T::...w();
>
> That makes 4 dots in a row...
>
=( Indeed. I think allowing packs as class members creates too many
problems, and probably isn't worth the trouble.
> This second approach is very problematic, and actually doesn't really make
>> sense from the user's perspective, nor from the mechanical perspective of
>> pack expansion. Consider:
>>
>> template<typename...T> using ...types = T;
>> types<int, char, double> f() { // return a pack
>> std::cout << "hello, world\n";
>> return {0, 0, 0};
>> }
>> template<typename...T> void g(T...);
>> template<typename...T> void h(T ...t) {
>> h(t ? f() : 0 ...);
>> }
>> void i() { h(true, false, true); }
>>
>> How many times is f() called here? It seems "obvious" to me that it
>> should get called once per pack expansion, just like any other code within
>> a pack expansion, and the message should be printed out twice. It's not
>> really clear that it'd be possible to support this kind of construct with
>> the "language magic" in approach 2 (where the message would somehow be
>> printed out once?).
>>
>
> Your example is quite convincing.
>
>
>
>> With f() returning a tuple, local variable packs, and explicit
>> packification, we get to write three different meaningful programs:
>>
>> template<typename...T> void h1(T ...t) {
>> // call 'f()' once for each element of 't' that is true, and use the
>> corresponding element of f()'s result
>> h(t ? ...f() : 0 ...);
>> }
>> template<typename...T> void h2(T ...t) {
>> // call 'f()' three times, put each slice of 'f' into a local
>> variable...
>> auto ...elems = ...f();
>> // ... and pass in the elements for which the corresponding element of
>> 't' is true
>> h(t ? elems : 0 ...);
>> }
>> template<typename...T> void h3(T ...t) {
>> // call 'f()' once...
>> auto elems = f();
>> // ... and pass in the elements for which the corresponding element of
>> 't' is true
>> h(t ? ...elems : 0 ...);
>> }
>>
>
> I'm a bit confused... are you mixing both our proposals in these examples?
> What is the meaning of ... as a prefix in these examples? (is it the
> meaning of my proposal or your proposal?)
>
The example assumes that we have both my proposal and local variable packs
(which are something which I think we both agree are desirable, and which
seem to not have any practical or theoretical problems).
> Also, I'm not sure I understand that third example. What is the type of
> elems?
>
Sorry, I should have included this with that example:
tuple<int, char, double> f() { // return a tuple, not a pack
std::cout << "hello, world\n";
return {0, 0, 0};
}
> I also have a question regarding your proposal. In the last part of my
> original post, I proposed 2 different ways to expand a template pack alias.
> It would allow the following (see my original post for more detailed
> examples):
>
> template <class... T>
> using... twice = types<T..., T...>;
>
> using... AB = types<A, B>;
> using... ABAB = twice<AB...>; // A, B, A, B
> using... AABB = twice<AB>...; // A, A, B, B
>
>
> Would the last line be possible with your proposal?
>
> template <class... T>
> using twice = types<T..., T...>;
>
> using AB = types<A, B>;
> using ABAB = twice<...AB...>;
> using AABB = ???;
>
>
This isn't quite as clean in my proposal:
using AABB = types<...twice<...AB>... ...>;
or perhaps more clearly:
template<typename...T> using concat = types<...T ... ...>;
using AABB = concat<twice<...AB> ...>;
How do you write concat in your proposal? I think you'd need a
pack-of-packs as a template parameter:
template<typename ... ...T> using ...concat = ... ...T ... ...;
right?
--
---
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/.
--089e0160c2dc4cef6704ec1abfee
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tue, Nov 26, 2013 at 7:25 AM, Alex B <span dir=3D"ltr">=
<<a href=3D"mailto:devalexb@gmail.com" target=3D"_blank">devalexb@gmail.=
com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail=
_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style=
:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><div><span style=3D"color:rgb(34,34,34)">Sorry, the example I meant was</s=
pan><br></div></div><div><br></div><div>=A0 template<typename T> void=
f(typename T::type ...);</div>
</div></div></div></blockquote><div><br></div></div><div>With the following=
syntax, there shouldn't be ambiguity:</div><div><br></div><div><font f=
ace=3D"courier new, monospace">template <typename T> void f(typename =
T::...type ...);</font></div>
<div><br></div><div>(similar to the following, which is not ambiguous:)</di=
v><div><br></div><div><font face=3D"courier new, monospace">template <ty=
pename... T> void f(T ...);</font></div><div class=3D"im"><div><font fac=
e=3D"courier new, monospace"><br>
</font></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_extra">
<div class=3D"gmail_quote"><div><div><span style=3D"color:rgb(34,34,34)">I =
think it'd be unfortunate to need to introduce another disambiguation s=
yntax (in addition to 'template' and 'typename').</span><br=
>
</div></div></div></div></div></blockquote><div><br></div></div><div>Well, =
that's what your proposal do (indirectly) as well. With your proposal, =
you have to prefix with an ellipsis everywhere. With mine, you only prefix =
with an ellipsis in ambiguous contexts.</div>
</div></div></div></blockquote><div><br></div><div>I don't see it that =
way. In my proposal, x and ...x are distinct things, and both are meaningfu=
l and useful. You only use the ... operator when you are converting a non-p=
ack into a pack -- it's *not* performing disambiguation, it's perfo=
rming a conversion to a different kind of entity.</div>
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div>To me, it sounds more consistent with actual syntax for declaring pack=
s:</div><div class=3D"im"><div><br></div><div><font face=3D"courier new, mo=
nospace">template <class... T></font></div><div><font face=3D"courier=
new, monospace">void f(T... t) {}</font></div>
<div><br></div></div><div>In the function declaration, we don't need to=
prefix T with another ellipsis to illustrate that it is a pack. In my prop=
osal, it's the same thing if T is an alias (except if it is an alias in=
a dependant name). In your proposal, you always need to prefix T with an e=
llipsis if it is an alias but never if it isn't. So to me, there is a t=
radeoff with both approaches. In some cases your approach is more ellegant,=
but in some other cases it is mine, like the following:</div>
<div><br></div><div><div><font face=3D"courier new, monospace">template <=
;int First, int... Others></font></div><div><font face=3D"courier new, m=
onospace">class A</font></div><div><font face=3D"courier new, monospace">{<=
/font></div>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>constexpr static int first =3D First;</font></div><div><font f=
ace=3D"courier new, monospace"><br></font></div><div><font face=3D"courier =
new, monospace"><span style=3D"white-space:pre-wrap"> </span>// Your propos=
al:</font></div>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>constexpr static auto others =3D std::make_tuple(Others...);</=
font></div><div><font face=3D"courier new, monospace"><span style=3D"white-=
space:pre-wrap"> </span>constexpr static auto all =3D std::make_tuple(first=
, ...others...);</font></div>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>constexpr static auto all2 =3D std::make_tuple(...all * 2 ...)=
;</font></div><div><font face=3D"courier new, monospace"><br></font></div><=
div>
<font face=3D"courier new, monospace"><span style=3D"white-space:pre-wrap">=
</span>// My proposal:</font></div><div><font face=3D"courier new, monospa=
ce"><span style=3D"white-space:pre-wrap"> </span>constexpr static int... ot=
hers =3D Others;</font></div>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>constexpr static int... all =3D std::make_pack(first, others..=
..);</font></div><div><font face=3D"courier new, monospace"><span style=3D"w=
hite-space:pre-wrap"> </span>constexpr static int... all2 =3D all * 2;</fon=
t></div>
<div><font face=3D"courier new, monospace"><div><br></div><div><span style=
=3D"white-space:pre-wrap"> </span>// Or if we do this in one line...</div><=
div><br></div><div><span style=3D"white-space:pre-wrap"> </span>// Your pro=
posal:</div>
<div><span style=3D"white-space:pre-wrap"> </span>constexpr static auto all=
2 =3D std::make_tuple(...std::make_tuple(First, Others...) * 2 ...);</div><=
div><br></div><div><span style=3D"white-space:pre-wrap"> </span>// My propo=
sal:</div>
<div><span style=3D"white-space:pre-wrap"> </span>constexpr static int... a=
ll2 =3D std::make_pack(First, Others...) * 2;</div></font></div><div><font =
face=3D"courier new, monospace">};</font></div></div><div class=3D"im"><div=
><br>
</div><div>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<div> Since different elements of a nested-name-specifier may or may not be=
packs, I think a better place for the ... would be after a ::. So:</div>
<div><br></div><div>=A0 typename T::...U::type // T::U is a pack</div><div>=
=A0 typename T::U::...type // T::U::type is a pack</div><div>=A0 T::...valu=
e // T::value is a pack</div></div></div></div></blockquote><div><br></div>=
</div>
<div>
That sounds better indeed.</div><div><br></div><div>Unfortunately, it gets =
a little dirtier when dealing with values:</div><div><br></div><div><div st=
yle=3D"color:rgb(80,0,80)"><font face=3D"courier new, monospace">=A0 =A0 =
=A0 icd... a =3D t. ...x;</font></div>
<div style=3D"color:rgb(80,0,80)"><font face=3D"courier new, monospace">=A0=
=A0 =A0 icd... b =3D t. ...y();</font></div><div style=3D"color:rgb(80,0,8=
0)"><font face=3D"courier new, monospace">=A0 =A0 =A0 icd... c =3D T::...z;=
</font></div><div style=3D"color:rgb(80,0,80)">
<font face=3D"courier new, monospace">=A0 =A0 =A0 icd... d =3D T::...w();</=
font></div></div><div><br></div><div>That makes 4 dots in a row...</div></d=
iv></div></div></blockquote><div><br></div><div>=3D( Indeed. I think allowi=
ng packs as class members creates too many problems, and probably isn't=
worth the trouble.</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra">=
<div class=3D"gmail_quote">
<div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><div><span style=3D"color:rgb(34,34,34)">This second approach is very prob=
lematic, and actually doesn't really make sense from the user's per=
spective, nor from the mechanical perspective of pack expansion. Consider:<=
/span><br>
</div></div>
<div><br></div><div>template<typename...T> using ...types =3D T;</div=
><div>types<int, char, double> f() { // return a pack</div><div>=A0 s=
td::cout << "hello, world\n";</div><div>=A0 return {0, 0, 0=
};</div>
<div>}</div><div>template<typename...T> void g(T...);</div><div>templ=
ate<typename...T> void h(T ...t) {</div><div>=A0 h(t ? f() : 0 ...);<=
/div><div>}</div><div>void i() { h(true, false, true); }</div><div><br></di=
v>
<div>How many times is f() called here? It seems "obvious" to me =
that it should get called once per pack expansion, just like any other code=
within a pack expansion, and the message should be printed out twice. It&#=
39;s not really clear that it'd be possible to support this kind of con=
struct with the "language magic" in approach 2 (where the message=
would somehow be printed out once?).</div>
</div></div></div></blockquote><div><br></div></div><div>Your example is qu=
ite convincing.</div><div class=3D"im"><div><br></div><div>=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">
<div>With f() returning a tuple, local variable packs, and explicit packifi=
cation, we get to write three different meaningful programs:<br></div><div>=
<br></div><div><div>template<typename...T> void h1(T ...t) {</div>
<div>=A0 // call 'f()' once for each element of 't' that is=
true, and use the corresponding element of f()'s result</div><div>=A0 =
h(t ? ...f() : 0 ...);<br></div><div>}</div></div><div><div>template<typ=
ename...T> void h2(T ...t) {</div>
<div>=A0 // call 'f()' three times, put each slice of 'f' i=
nto a local variable...</div><div>=A0 auto ...elems =3D ...f();</div><div>=
=A0 // ... and pass in the elements for which the corresponding element of =
't' is true</div>
<div>=A0 h(t ? elems : 0 ...);</div><div>}</div></div><div><div><div>templa=
te<typename...T> void h3(T ...t) {</div><div>=A0 // call 'f()'=
; once...</div><div>=A0 auto elems =3D f();</div><div>=A0 // ... and pass i=
n the elements for which the corresponding element of 't' is true</=
div>
<div>=A0 h(t ? ...elems : 0 ...);</div><div>}</div></div></div></div></div>=
</div></blockquote><div><br></div></div><div>I'm a bit confused... are =
you mixing both our proposals in these examples? What is the meaning of ...=
as a =A0prefix in these examples? (is it the meaning of my proposal or you=
r proposal?)</div>
</div></div></div></blockquote><div><br></div><div>The example assumes that=
we have both my proposal and local variable packs (which are something whi=
ch I think we both agree are desirable, and which seem to not have any prac=
tical or theoretical problems).</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra">=
<div class=3D"gmail_quote">
<div>Also, I'm not sure I understand that third example. What is the ty=
pe of elems?</div></div></div></div></blockquote><div><br></div><div>Sorry,=
I should have included this with that example:</div><div><br></div><div>
<div>tuple<int, char, double> f() { // return a tuple, not a pack</di=
v><div>=A0 std::cout << "hello, world\n";</div><div>=A0 ret=
urn {0, 0, 0};</div><div>}</div></div><div>=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>I also have a question regarding your proposal. In the last part of my ori=
ginal post, I proposed 2 different ways to expand a template pack alias. It=
would allow the following (see my original post for more detailed examples=
):</div>
<div><br></div></div></div><blockquote style=3D"margin:0px 0px 0px 40px;bor=
der:none;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><div><div><font face=3D"courier new, monospace">template <class... T>=
;</font></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><div><font face=3D"courier new, monospace">using... twice =3D types<T.=
..., T...>;</font></div></div></div></div><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<div><div><font face=3D"courier new, monospace"><br></font></div></div></di=
v></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><div><fo=
nt face=3D"courier new, monospace">using... AB =3D types<A, B>;</font=
></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><div><font face=3D"courier new, monospace">using... ABAB =3D twice<AB.=
...>; // A, B, A, B</font></div></div></div></div><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote">
<div><div><font face=3D"courier new, monospace">using... AABB =3D twice<=
AB>...; // A, A, B, B</font></div></div></div></div></blockquote><div cl=
ass=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></div><div>Would th=
e last line be possible with your proposal?</div>
<div><br></div></div></div><blockquote style=3D"margin:0px 0px 0px 40px;bor=
der:none;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><div><div><font face=3D"courier new, monospace">template <class... T>=
;</font></div>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><font face=3D"courier new, monospace">using twice =3D types<T..., T...=
>;</font></div></div></div><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote">
<div><font face=3D"courier new, monospace"><br></font></div></div></div><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"couri=
er new, monospace">using AB =3D types<A, B>;</font></div></div></div>=
<div class=3D"gmail_extra">
<div class=3D"gmail_quote"><div><font face=3D"courier new, monospace">using=
ABAB =3D twice<...AB...>;</font></div></div></div><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div><font face=3D"courier new, monospa=
ce">using AABB =3D ???;</font></div>
</div></div></blockquote></div></blockquote><div><br></div><div>This isn=
9;t quite as clean in my proposal:</div><div><br></div><div>=A0 using AABB =
=3D types<...twice<...AB>... ...>;</div><div><br></div><div>or =
perhaps more clearly:</div>
<div><br></div><div>=A0 template<typename...T> using concat =3D types=
<...T ... ...>;</div><div>=A0 using AABB =3D concat<twice<...AB=
> ...>;</div><div><br></div><div><br></div><div>How do you write conc=
at in your proposal? I think you'd need a pack-of-packs as a template p=
arameter:</div>
<div><br></div><div>=A0 template<typename ... ...T> using ...concat =
=3D ... ...T ... ...;</div><div><br></div><div>right?</div></div></div></di=
v>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0160c2dc4cef6704ec1abfee--
.
Author: Alex B <devalexb@gmail.com>
Date: Wed, 27 Nov 2013 10:36:10 -0500
Raw View
--001a11362ee845ccd604ec2a5b46
Content-Type: text/plain; charset=ISO-8859-1
>
> The example assumes that we have both my proposal and local variable packs
> (which are something which I think we both agree are desirable, and which
> seem to not have any practical or theoretical problems).
>
Well, to me, variable packs are desirable only if we support them in all
contexts (not if only local context). If we can't agree on a way to support
them in all contexts, it just sound to me that we didn't yet nailed the
right design. Even if it would practically and theoretically work in local
contexts, the chosen syntax might get in the way if we (someday) find a
reasonable way to add it in other contexts.
> How do you write concat in your proposal?
>
I don't see a need for a thing like concat in my proposal. The following
alias is enough:
template <class... T> using... types = T;`
using... packA = /*...*/;
using... packB = /*...*/;
using... concatenated = types<packA..., packB...>;
I think you'd need a pack-of-packs as a template parameter:
>
> template<typename ... ...T> using ...concat = ... ...T ... ...;
>
> right?
>
Uh... no, unexpanded packs as template parameters would cause a bunch of
problems. Even more if we are talking about "a pack of unexpanded packs".
I'm pretty sure we don't want to go in that direction :)
To sum things up, we seem to agree that:
- Variable packs should not cause any problems when declared in
function-local contexts. I guess the same could be said about global/
namespace context, right? Ambiguity problems begin to arise for member
declarations.
- All the same could probably be said about type pack aliases, right? They
have ambiguity problems only when declared as a member.
- Same for functions returning packs.
I also am all for your proposal about adding a packification operator (both
for types and values). The only thing that I proposed so far that was in
conflict with that is to use an ellipsis as a prefix to disambiguate packs
(when needed). Even if we were to only consider my proposal, we saw that
this way to disambiguate was sometimes not very nice (resulting in things
like 4 dots in a row).
Still, I would really like to find a clean syntax to disambiguate packs
(and make sure that disambiguation syntax doesn't conflict with the
packification syntax that you propose). That way we could allow widespread
support (in all contexts) for variable packs, type pack aliases and
functions returning packs.
What about (...) as a way to disambiguate? (not sure in that case if it
should be called a keyword or an operator)
icd... a = t.(...)x;
icd... b = t.(...)y();
icd... c = T::(...)z;
icd... d = T::(...)w();
template <typename T> void f(typename T::(...)type ...);
Or maybe [...] or {...} would be better. Or maybe a keyword like "pack"
would be better.
--
---
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/.
--001a11362ee845ccd604ec2a5b46
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><div><div>The example assumes that we have both my proposal and local vari=
able packs (which are something which I think we both agree are desirable, =
and which seem to not have any practical or theoretical problems).<br>
</div></div></div></div></div></div></blockquote><div><br></div><div>Well, =
to me, variable packs are desirable only if we support them in all contexts=
(not if only local context). If we can't agree on a way to support the=
m in all contexts, it just sound to me that we didn't yet nailed the ri=
ght design. Even if it would practically and theoretically work in local co=
ntexts, the chosen syntax might get in the way if we (someday) find a reaso=
nable way to add it in other contexts.</div>
<div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra">
<div class=3D"gmail_quote"><div>How do you write concat in your proposal?</=
div></div></div></div></blockquote><div><br></div><div>I don't see a ne=
ed for a thing like <span class=3D"" style>concat</span> in my proposal. Th=
e following alias is enough:</div>
<div><br></div></div></div><blockquote style=3D"margin:0px 0px 0px 40px;bor=
der:none;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><div><font face=3D"courier new, monospace">template <class... T> usi=
ng... types =3D T;`</font></div>
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"courier new, monospace"><br></font></div></div></div><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"courier new,=
monospace">using... <span class=3D"" style>packA</span> =3D /*...*/;</font=
></div>
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"courier new, monospace">using... <span class=3D"" style>packB</sp=
an> =3D /*...*/;</font></div></div></div><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote">
<div><font face=3D"courier new, monospace">using... concatenated =3D types&=
lt;<span class=3D"" style>packA</span>..., <span class=3D"" style>packB</sp=
an>...>;</font></div></div></div></blockquote><div class=3D"gmail_extra"=
><div class=3D"gmail_quote">
<div>=A0</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra">
<div class=3D"gmail_quote"><div>I think you'd need a pack-of-packs as a=
template parameter:</div>
<div><br></div><div>=A0 template<typename ... ...T> using ...concat =
=3D ... ...T ... ...;</div><div><br></div><div>right?</div></div></div></di=
v></blockquote><div><br></div><div>Uh... no, unexpanded packs as template p=
arameters would cause a bunch of problems. Even more if we are talking abou=
t "a pack of unexpanded packs". I'm pretty sure we don't =
want to go in that direction :)</div>
<div><br></div><div><br></div><div>To sum things up, we seem to agree that:=
</div><div>- Variable packs should not cause any problems when declared in =
function-local contexts. I guess the same could be said about global/<span =
class=3D"" style>namespace</span> context, right? Ambiguity problems begin =
to arise for member declarations.</div>
<div>- All the same could probably be said about type pack aliases, right? =
They have ambiguity problems only when declared as a member.</div><div>- Sa=
me for functions returning packs.</div><div><br></div><div>I also am all fo=
r your proposal about adding a <span class=3D"" style>packification</span> =
operator (both for types and values). The only thing that I proposed so far=
that was in conflict with that is to use an ellipsis as a prefix to disamb=
iguate packs (when needed). Even if we were to only consider my proposal, w=
e saw that this way to disambiguate was sometimes not very nice (resulting =
in things like 4 dots in a row).</div>
<div><br></div><div>Still, I would really like to find a clean syntax to di=
sambiguate packs (and make sure that disambiguation syntax doesn't conf=
lict with the <span class=3D"" style>packification</span> syntax that you p=
ropose). That way we could allow widespread support (in all contexts) for v=
ariable packs, type pack aliases and functions returning packs.</div>
<div><br></div><div>What about (...) as a way to disambiguate? (not sure in=
that case if it should be called a keyword or an operator)</div><div><br><=
/div><div><div><font face=3D"courier new, monospace"><span class=3D"" style=
>icd</span>... a =3D t.(...)x;</font></div>
<div><font face=3D"courier new, monospace"><span class=3D"" style>icd</span=
>... b =3D t.(...)y();</font></div><div><font face=3D"courier new, monospac=
e"><span class=3D"" style>icd</span>... c =3D T::(...)z;</font></div><div><=
font face=3D"courier new, monospace"><span class=3D"" style>icd</span>... d=
=3D T::(...)w();</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">template <<span class=3D"" style>typename</s=
pan> T> void f(<span class=3D"" style>typename</span> T::(...)type ...);=
</font></div>
</div><div><br></div><div>Or maybe [...] or {...} would be better. Or maybe=
a keyword like "pack" would be better.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11362ee845ccd604ec2a5b46--
.
Author: Xavi Gratal <gratal@gmail.com>
Date: Fri, 6 Dec 2013 04:29:56 -0800 (PST)
Raw View
------=_Part_67_16580350.1386332996627
Content-Type: text/plain; charset=ISO-8859-1
On a related note, why is parameter pack expansion only allowed in the
context of a function call?
I have the following code:
const std::string &to_string(const std::string &str) { return str; }
void do_concat(std::string&) {}
template<typename... rest_t>
void do_concat(std::string &str,const std::string &next,const rest_t&...rest
) {
str+=next;
do_concat(str,rest...);
}
template<typename... args_t>
std::string make_string(const args_t&... args) {
using std::to_string;
using ::to_string;
std::string str;
do_concat(str,to_string(args)...);
return str;
}
int main()
{
std::cout << make_string("aaa ",1," bbb ",1.3) << "\n";
}
Which works fine, but if we allowed parameter pack statement expansion,
make_string could be implemented as:
template<typename... args_t>
std::string make_string(const args_t&... args) {
using std::to_string;
using ::to_string;
std::string str;
(str+=to_string(args))...;
return str;
}
and do_concat would no longer be necessary. It is almost possible to do it
with:
template<typename... args_t> do_nothing(const args_t&... args) {}
template<typename... args_t>
std::string make_string(const args_t&... args) {
using std::to_string;
using ::to_string;
std::string str;
do_nothing((str+=to_string(args))...);
return str;
}
except that the result is not the expected one, since the arguments to
do_nothing are evaluated in arbitrary order.
Was there any specific reason to disallow expansion outside of a function
call? Is there any simpler way to implement make_string?
--
---
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/.
------=_Part_67_16580350.1386332996627
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On a related note, why is parameter pack expansion only al=
lowed in the context of a function call?<div>I have the following code:</di=
v><div><br></div><div><div class=3D"prettyprint" style=3D"background-color:=
rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break=
-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">string</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">to_string</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">str</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">r=
eturn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> str<=
/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: #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-prettify">void</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> do_concat</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-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">string</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><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: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> rest_t</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: #008;" clas=
s=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> do_concat</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">strin=
g</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">str</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">string</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"=
>next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> rest_t</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">&...</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> rest</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> str</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">+=3D</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">next</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br> do_concat</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">str</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">rest</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...)=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></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><br></span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">template</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: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> args_t</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>std</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">string</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> make_string</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ar=
gs_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&.=
...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> args</s=
pan><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> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">using</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">to_string</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">using</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">to_string</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=
std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">s=
tring</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> str<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> do=
_concat</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">str</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">to_string</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)...);</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br> </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> str</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-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=
"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> main</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br> std</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">cout </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><<</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> make_string</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" =
class=3D"styled-by-prettify">"aaa "</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #066;" class=3D"styl=
ed-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: #080;" class=3D"styled-by-prettify">" =
bbb "</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">1.3</span><spa=
n 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"> </span><span style=3D"color: #080;" cl=
ass=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-b=
y-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span></div></code></div><div><br></div><div>Which works fine, but if we =
allowed parameter pack statement expansion, make_string could be implemente=
d as:</div><div><br></div><div class=3D"prettyprint" style=3D"background-co=
lor: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span s=
tyle=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: #660;" class=3D"styled-by-prettify">...</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> args_t</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">string</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> make_string</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> args_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </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> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">using</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">to_string</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: #008=
;" class=3D"styled-by-prettify">using</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">to_string</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br> std</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">string</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> str</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &=
nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">str</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">to_string</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">))...;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br> </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> str</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div><div><br></div>and do_concat would no long=
er be necessary. It is almost possible to do it with:</div><div><br></div><=
div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187=
); background-color: rgb(250, 250, 250); word-wrap: break-word;"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify">template</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: #660;" class=
=3D"styled-by-prettify">...</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> args_t</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> do_nothing</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> args=
_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&...=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> args</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{}</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">template</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: #660;" class=
=3D"styled-by-prettify">...</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> args_t</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>std</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
ing</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> make_s=
tring</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> args_t</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">&...</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> args</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> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">using</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">to_string</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">using</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">to_string</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><br> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> str</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> do_nothing</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">((</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">str</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">+=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">to_string</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">args</span><span style=3D"color: #660;" 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-pre=
ttify"><br> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> str</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></=
code></div><div><br></div><div>except that the result is not the expected o=
ne, since the arguments to do_nothing are evaluated in arbitrary order.</di=
v><div><br></div><div>Was there any specific reason to disallow expansion o=
utside of a function call? Is there any simpler way to implement make_strin=
g?</div></div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_67_16580350.1386332996627--
.
Author: Alex B <devalexb@gmail.com>
Date: Fri, 6 Dec 2013 09:44:27 -0500
Raw View
--001a11345fdcd9ef1104ecdeae09
Content-Type: text/plain; charset=ISO-8859-1
I guess the reason is to initially make it simple and uniform to expand a
pack. Right now, the equivalent of a pack expansion is as simple as
separating each elements of the pack by a comma and nothing else. Note that
current rules do not only allow to expand in function call but in other
contexts as well.
Here is one example:
template <class... Bases>
class Derived : public Bases...
{};
And another one:
template <int... Values>
void f()
{
int values[] = { Values... };
}
As you can see, all current use cases are expanded by adding a comma
between each expanded elements.
One of the things Richard suggested in this thread was adding a new meaning
to the unpack operator when it is followed by a semicolon. It would be
expanded into several expression statement.
Now about the problem you are trying to solve with the current standard,
just convert your 'do_nothing' function to a class instead and call its
constructor using list-initialization:
do_nothing{(str += to_string(args))...};
This is guaranteed to be evaluated left to right (note that Richard did
talk about something like this in the current thread when he was referring
to a class named 'sink'). But of course, it would be nicer if this
workaround wasn't needed.
You can even expand over several statements using a lambda:
do_nothing{[&]() {
str += to_string(args);
str += separator;
}() ...};
I saw someone in another thread propose expanding packs in a for-range
fashion (using a 'for...' syntax):
for... (const auto& a : args) {
str += to_string(a);
str += separator;
}
I like this idea a lot, but I'm not sure the one who proposed it will go
forward with it.
Something similar can currently be done if we expand all elements into an
initializer list:
for (const auto& a : { to_string(args)... }) {
str += a;
str += separator;
}
It works in this example but requires that all elements are expanded to a
single type. It is not always wanted or even possible to convert all
elements to a single type.
On Fri, Dec 6, 2013 at 7:29 AM, Xavi Gratal <gratal@gmail.com> wrote:
> On a related note, why is parameter pack expansion only allowed in the
> context of a function call?
> I have the following code:
>
> const std::string &to_string(const std::string &str) { return str; }
>
> void do_concat(std::string&) {}
>
> template<typename... rest_t>
> void do_concat(std::string &str,const std::string &next,const rest_t&...rest
> ) {
> str+=next;
> do_concat(str,rest...);
> }
>
> template<typename... args_t>
> std::string make_string(const args_t&... args) {
> using std::to_string;
> using ::to_string;
>
> std::string str;
> do_concat(str,to_string(args)...);
> return str;
> }
>
> int main()
> {
> std::cout << make_string("aaa ",1," bbb ",1.3) << "\n";
> }
>
> Which works fine, but if we allowed parameter pack statement expansion,
> make_string could be implemented as:
>
> template<typename... args_t>
> std::string make_string(const args_t&... args) {
> using std::to_string;
> using ::to_string;
>
> std::string str;
> (str+=to_string(args))...;
> return str;
> }
>
> and do_concat would no longer be necessary. It is almost possible to do it
> with:
>
> template<typename... args_t> do_nothing(const args_t&... args) {}
>
> template<typename... args_t>
> std::string make_string(const args_t&... args) {
> using std::to_string;
> using ::to_string;
>
> std::string str;
> do_nothing((str+=to_string(args))...);
> return str;
> }
>
> except that the result is not the expected one, since the arguments to
> do_nothing are evaluated in arbitrary order.
>
> Was there any specific reason to disallow expansion outside of a function
> call? Is there any simpler way to implement make_string?
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/.
>
--
---
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/.
--001a11345fdcd9ef1104ecdeae09
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I guess the reason is to initially make it simple and unif=
orm to expand a pack. Right now, the equivalent of a pack expansion is as s=
imple as separating each elements of the pack by a comma and nothing else. =
Note that current rules do not only allow to expand in function call but in=
other contexts as well.<div>
<br></div><div>Here is one example:</div><div><br></div><blockquote style=
=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"cou=
rier new, monospace">template <class... Bases></font></div><div><font=
face=3D"courier new, monospace">class Derived : public Bases...</font></di=
v>
<div><font face=3D"courier new, monospace">{};</font></div></blockquote><di=
v><br></div><div>And another one:</div><div><br></div><blockquote style=3D"=
margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"courier=
new, monospace">template <int... Values></font></div>
<div><font face=3D"courier new, monospace">void f()</font></div><div><font =
face=3D"courier new, monospace">{</font></div><div><font face=3D"courier ne=
w, monospace">=A0 =A0 int values[] =3D { Values... };</font></div><div><fon=
t face=3D"courier new, monospace">}</font></div>
</blockquote><div><br></div><div>As you can see, all current use cases are =
expanded by adding a comma between each expanded elements.</div><div><br></=
div><div>One of the things Richard suggested in this thread was adding a ne=
w meaning to the unpack operator when it is followed by a semicolon. It wou=
ld be expanded into several expression statement.</div>
<div><br></div><div>Now about the problem you are trying to solve with the =
current standard, just convert your 'do_nothing' function to a clas=
s instead and call its constructor using list-initialization:</div><div>
<br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><=
font face=3D"courier new, monospace">do_nothing{(str +=3D to_string(args)).=
...};</font></blockquote><div><br></div><div>This is guaranteed to be evalua=
ted left to right (note that Richard did talk about something like this in =
the current thread when he was referring to a class named 'sink'). =
But of course, it would be nicer if this workaround wasn't needed.</div=
>
<div><br></div><div>You can even expand over several statements using a lam=
bda:</div><div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none=
;padding:0px"><div><font face=3D"courier new, monospace">do_nothing{[&]=
() {</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 str +=3D to_string(args)=
;</font></div><div><font face=3D"courier new, monospace">=A0 =A0 str +=3D s=
eparator;</font></div><div><font face=3D"courier new, monospace">}() ...};<=
/font></div></blockquote>
<div><br></div><div>I saw someone in another thread propose expanding packs=
in a for-range fashion (using a 'for...' syntax):</div><div><br></=
div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>
<font face=3D"courier new, monospace">for... (const auto& a : args) {</=
font></div><div><font face=3D"courier new, monospace">=A0 =A0 str +=3D to_s=
tring(a);</font></div><div><font face=3D"courier new, monospace">=A0 =A0 st=
r +=3D separator;</font></div>
<div><font face=3D"courier new, monospace">}</font></div></blockquote><div>=
<br></div><div>I like this idea a lot, but I'm not sure the one who pro=
posed it will go forward with it.</div><div><br></div><div>Something simila=
r can currently be done if we expand all elements into an initializer list:=
</div>
<div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0=
px"><div><font face=3D"courier new, monospace">for (const auto& a : { t=
o_string(args)... })=A0{</font></div><div><font face=3D"courier new, monosp=
ace">=A0 =A0 str +=3D a;</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 str +=3D separator;</fon=
t></div><div><font face=3D"courier new, monospace">}</font></div></blockquo=
te><div><br></div><div>It works in this example but requires that all eleme=
nts are expanded to a single type. It is not always wanted or even possible=
to convert all elements to a single type.</div>
</div><div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Fri,=
Dec 6, 2013 at 7:29 AM, Xavi Gratal <span dir=3D"ltr"><<a href=3D"mailt=
o:gratal@gmail.com" target=3D"_blank">gratal@gmail.com</a>></span> wrote=
:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr">On a related note, why is parameter pack expansion only al=
lowed in the context of a function call?<div>I have the following code:</di=
v><div><br></div><div><div style=3D"background-color:rgb(250,250,250);borde=
r:1px solid rgb(187,187,187);word-wrap:break-word">
<code><div><span style=3D"color:#008">const</span><span style> std</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#008">string</span><=
span style> </span><span style=3D"color:#660">&</span><span style>to_st=
ring</span><span style=3D"color:#660">(</span><span style=3D"color:#008">co=
nst</span><span style> std</span><span style=3D"color:#660">::</span><span =
style=3D"color:#008">string</span><span style> </span><span style=3D"color:=
#660">&</span><span style>str</span><span style=3D"color:#660">)</span>=
<span style> </span><span style=3D"color:#660">{</span><span style> </span>=
<span style=3D"color:#008">return</span><span style> str</span><span style=
=3D"color:#660">;</span><span style> </span><span style=3D"color:#660">}</s=
pan><span style><br>
<br></span><span style=3D"color:#008">void</span><span style> do_concat</sp=
an><span style=3D"color:#660">(</span><span style>std</span><span style=3D"=
color:#660">::</span><span style=3D"color:#008">string</span><span style=3D=
"color:#660">&)</span><span style> </span><span style=3D"color:#660">{}=
</span><span style><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span style> rest_t</span><span style=3D"color:#660">&g=
t;</span><span style><br>
</span><span style=3D"color:#008">void</span><span style> do_concat</span><=
span style=3D"color:#660">(</span><span style>std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#008">string</span><span style> </spa=
n><span style=3D"color:#660">&</span><span style>str</span><span style=
=3D"color:#660">,</span><span style=3D"color:#008">const</span><span style>=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">s=
tring</span><span style> </span><span style=3D"color:#660">&</span><spa=
n style=3D"color:#008">next</span><span style=3D"color:#660">,</span><span =
style=3D"color:#008">const</span><span style> rest_t</span><span style=3D"c=
olor:#660">&...</span><span style> rest</span><span style=3D"color:#660=
">)</span><span style> </span><span style=3D"color:#660">{</span><span styl=
e><br>
=A0 =A0 str</span><span style=3D"color:#660">+=3D</span><span style=3D"colo=
r:#008">next</span><span style=3D"color:#660">;</span><span style><br>=A0 =
=A0 do_concat</span><span style=3D"color:#660">(</span><span style>str</spa=
n><span style=3D"color:#660">,</span><span style>rest</span><span style=3D"=
color:#660">...);</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br><br></span><span =
style=3D"color:#008">template</span><span style=3D"color:#660"><</span><=
span style=3D"color:#008">typename</span><span style=3D"color:#660">...</sp=
an><span style> args_t</span><span style=3D"color:#660">></span><span st=
yle><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span style> make_string</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#008">const</span><span style> args_t</span><span st=
yle=3D"color:#660">&...</span><span style> args</span><span style=3D"co=
lor:#660">)</span><span style> </span><span style=3D"color:#660">{</span><s=
pan style><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span style> std</spa=
n><span style=3D"color:#660">::</span><span style>to_string</span><span sty=
le=3D"color:#660">;</span><span style><br>=A0 =A0 </span><span style=3D"col=
or:#008">using</span><span style> </span><span style=3D"color:#660">::</spa=
n><span style>to_string</span><span style=3D"color:#660">;</span><span styl=
e><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span style> str</span><span style=3D"color:#660">;<=
/span><span style><br>=A0 =A0 do_concat</span><span style=3D"color:#660">(<=
/span><span style>str</span><span style=3D"color:#660">,</span><span style>=
to_string</span><span style=3D"color:#660">(</span><span style>args</span><=
span style=3D"color:#660">)...);</span><span style><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span style> str</sp=
an><span style=3D"color:#660">;</span><span style><br></span><span style=3D=
"color:#660">}</span><span style><br><br></span><span style=3D"color:#008">=
int</span><span style> main</span><span style=3D"color:#660">()</span><span=
style><br>
</span><span style=3D"color:#660">{</span><span style><br>=A0 =A0 std</span=
><span style=3D"color:#660">::</span><span style>cout </span><span style=3D=
"color:#660"><<</span><span style> make_string</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#080">"aaa "</span><span =
style=3D"color:#660">,</span><span style=3D"color:#066">1</span><span style=
=3D"color:#660">,</span><span style=3D"color:#080">" bbb "</span>=
<span style=3D"color:#660">,</span><span style=3D"color:#066">1.3</span><sp=
an style=3D"color:#660">)</span><span style> </span><span style=3D"color:#6=
60"><<</span><span style> </span><span style=3D"color:#080">"\n&=
quot;</span><span style=3D"color:#660">;</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><div><br></div><div>Which works fine, but if we allowed parameter =
pack statement expansion, make_string could be implemented as:</div><div>
<br></div><div style=3D"background-color:rgb(250,250,250);border:1px solid =
rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"color:#008=
">template</span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#660">...</span><span style> arg=
s_t</span><span style=3D"color:#660">></span><span style><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span style> make_string</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#008">const</span><span style> args_t</span><span st=
yle=3D"color:#660">&...</span><span style> args</span><span style=3D"co=
lor:#660">)</span><span style> </span><span style=3D"color:#660">{</span><s=
pan style><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span style> std</spa=
n><span style=3D"color:#660">::</span><span style>to_string</span><span sty=
le=3D"color:#660">;</span><span style><br>=A0 =A0 </span><span style=3D"col=
or:#008">using</span><span style> </span><span style=3D"color:#660">::</spa=
n><span style>to_string</span><span style=3D"color:#660">;</span><span styl=
e><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span style> str</span><span style=3D"color:#660">;<=
/span><span style><br>=A0 =A0 </span><span style=3D"color:#660">(</span><sp=
an style>str</span><span style=3D"color:#660">+=3D</span><span style>to_str=
ing</span><span style=3D"color:#660">(</span><span style>args</span><span s=
tyle=3D"color:#660">))...;</span><span style><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span style> str</sp=
an><span style=3D"color:#660">;</span><span style><br></span><span style=3D=
"color:#660">}</span><span style><br></span></div></code></div><div><br></d=
iv>and do_concat would no longer be necessary. It is almost possible to do =
it with:</div>
<div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);backgro=
und-color:rgb(250,250,250);word-wrap:break-word"><code><div><span style=3D"=
color:#008">template</span><span style=3D"color:#660"><</span><span styl=
e=3D"color:#008">typename</span><span style=3D"color:#660">...</span><span =
style> args_t</span><span style=3D"color:#660">></span><span style> do_n=
othing</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
const</span><span style> args_t</span><span style=3D"color:#660">&...</=
span><span style> args</span><span style=3D"color:#660">)</span><span style=
> </span><span style=3D"color:#660">{}</span><span style><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span style> args_t</span><span style=3D"color:#660">&g=
t;</span><span style><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span style> make_string</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#008">const</span><span style> args_t</span><span st=
yle=3D"color:#660">&...</span><span style> args</span><span style=3D"co=
lor:#660">)</span><span style> </span><span style=3D"color:#660">{</span><s=
pan style><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span style> std</spa=
n><span style=3D"color:#660">::</span><span style>to_string</span><span sty=
le=3D"color:#660">;</span><span style><br>=A0 =A0 </span><span style=3D"col=
or:#008">using</span><span style> </span><span style=3D"color:#660">::</spa=
n><span style>to_string</span><span style=3D"color:#660">;</span><span styl=
e><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span style> str</span><span style=3D"color:#660">;<=
/span><span style><br>=A0 =A0 do_nothing</span><span style=3D"color:#660">(=
(</span><span style>str</span><span style=3D"color:#660">+=3D</span><span s=
tyle>to_string</span><span style=3D"color:#660">(</span><span style>args</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#660">)...);</s=
pan><span style><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span style> str</sp=
an><span style=3D"color:#660">;</span><span style><br></span><span style=3D=
"color:#660">}</span><span style><br></span></div></code></div><div><br></d=
iv><div>
except that the result is not the expected one, since the arguments to do_n=
othing are evaluated in arbitrary order.</div><div><br></div><div>Was there=
any specific reason to disallow expansion outside of a function call? Is t=
here any simpler way to implement make_string?</div>
</div><div><br></div></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
=A0<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ=
/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D"_blank">std-pr=
oposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11345fdcd9ef1104ecdeae09--
.
Author: xavi <gratal@gmail.com>
Date: Fri, 6 Dec 2013 16:23:37 +0100
Raw View
--089e01536a84eb65a104ecdf3a8c
Content-Type: text/plain; charset=ISO-8859-1
Thanks a lot for the explanation!
2013/12/6 Alex B <devalexb@gmail.com>
> I guess the reason is to initially make it simple and uniform to expand a
> pack. Right now, the equivalent of a pack expansion is as simple as
> separating each elements of the pack by a comma and nothing else. Note that
> current rules do not only allow to expand in function call but in other
> contexts as well.
>
> Here is one example:
>
> template <class... Bases>
> class Derived : public Bases...
> {};
>
>
> And another one:
>
> template <int... Values>
> void f()
> {
> int values[] = { Values... };
> }
>
>
> As you can see, all current use cases are expanded by adding a comma
> between each expanded elements.
>
> One of the things Richard suggested in this thread was adding a new
> meaning to the unpack operator when it is followed by a semicolon. It would
> be expanded into several expression statement.
>
> It wouldn't even be necessary to change the simple and uniform way to
expand a pack you mention. If instead of being expanded into several
expression statements, it was expanded into a single comma-separated
expression, it would still work, since operands to the comma operator are
always evaluated left-to right. It would of course behave differently if
the comma operator is overloaded for the result type, but if you overloaded
the comma operator, that's probably what you want.
> Now about the problem you are trying to solve with the current standard,
> just convert your 'do_nothing' function to a class instead and call its
> constructor using list-initialization:
>
> do_nothing{(str += to_string(args))...};
>
>
> That's great... the only drawback of this (apart from being more verbose)
is that it doesn't work when the result of the expression is of type void,
while the operands of the comma operator can both be of type void.
I guess a workaround would be:
do_nothing{ (func_returning_void(args), 0)... };
but it's getting a bit loaded on workarounds.
> This is guaranteed to be evaluated left to right (note that Richard did
> talk about something like this in the current thread when he was referring
> to a class named 'sink'). But of course, it would be nicer if this
> workaround wasn't needed.
>
> You can even expand over several statements using a lambda:
>
> do_nothing{[&]() {
> str += to_string(args);
> str += separator;
> }() ...};
>
>
> I saw someone in another thread propose expanding packs in a for-range
> fashion (using a 'for...' syntax):
>
> for... (const auto& a : args) {
> str += to_string(a);
> str += separator;
> }
>
>
> I like this idea a lot, but I'm not sure the one who proposed it will go
> forward with it.
>
> Something similar can currently be done if we expand all elements into an
> initializer list:
>
> for (const auto& a : { to_string(args)... }) {
> str += a;
> str += separator;
> }
>
>
> It works in this example but requires that all elements are expanded to a
> single type. It is not always wanted or even possible to convert all
> elements to a single type.
>
>
> On Fri, Dec 6, 2013 at 7:29 AM, Xavi Gratal <gratal@gmail.com> wrote:
>
>> On a related note, why is parameter pack expansion only allowed in the
>> context of a function call?
>> I have the following code:
>>
>> const std::string &to_string(const std::string &str) { return str; }
>>
>> void do_concat(std::string&) {}
>>
>> template<typename... rest_t>
>> void do_concat(std::string &str,const std::string &next,const rest_t&...rest
>> ) {
>> str+=next;
>> do_concat(str,rest...);
>> }
>>
>> template<typename... args_t>
>> std::string make_string(const args_t&... args) {
>> using std::to_string;
>> using ::to_string;
>>
>> std::string str;
>> do_concat(str,to_string(args)...);
>> return str;
>> }
>>
>> int main()
>> {
>> std::cout << make_string("aaa ",1," bbb ",1.3) << "\n";
>> }
>>
>> Which works fine, but if we allowed parameter pack statement expansion,
>> make_string could be implemented as:
>>
>> template<typename... args_t>
>> std::string make_string(const args_t&... args) {
>> using std::to_string;
>> using ::to_string;
>>
>> std::string str;
>> (str+=to_string(args))...;
>> return str;
>> }
>>
>> and do_concat would no longer be necessary. It is almost possible to do
>> it with:
>>
>> template<typename... args_t> do_nothing(const args_t&... args) {}
>>
>> template<typename... args_t>
>> std::string make_string(const args_t&... args) {
>> using std::to_string;
>> using ::to_string;
>>
>> std::string str;
>> do_nothing((str+=to_string(args))...);
>> return str;
>> }
>>
>> except that the result is not the expected one, since the arguments to
>> do_nothing are evaluated in arbitrary order.
>>
>> Was there any specific reason to disallow expansion outside of a function
>> call? Is there any simpler way to implement make_string?
>>
>> --
>>
>> ---
>> You received this message because you are subscribed to a topic in the
>> Google Groups "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, 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/.
>>
>
> --
>
> ---
> 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/.
>
--
---
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/.
--089e01536a84eb65a104ecdf3a8c
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Thanks a lot for the explanation!<br><div class=3D"gmail_e=
xtra"><br><br><div class=3D"gmail_quote">2013/12/6 Alex B <span dir=3D"ltr"=
><<a href=3D"mailto:devalexb@gmail.com" target=3D"_blank">devalexb@gmail=
..com</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">I guess the reason is to in=
itially make it simple and uniform to expand a pack. Right now, the equival=
ent of a pack expansion is as simple as separating each elements of the pac=
k by a comma and nothing else. Note that current rules do not only allow to=
expand in function call but in other contexts as well.<div>
<br></div><div>Here is one example:</div><div><br></div><blockquote style=
=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"cou=
rier new, monospace">template <class... Bases></font></div><div><font=
face=3D"courier new, monospace">class Derived : public Bases...</font></di=
v>
<div><font face=3D"courier new, monospace">{};</font></div></blockquote><di=
v><br></div><div>And another one:</div><div><br></div><blockquote style=3D"=
margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"courier=
new, monospace">template <int... Values></font></div>
<div><font face=3D"courier new, monospace">void f()</font></div><div><font =
face=3D"courier new, monospace">{</font></div><div><font face=3D"courier ne=
w, monospace">=A0 =A0 int values[] =3D { Values... };</font></div><div><fon=
t face=3D"courier new, monospace">}</font></div>
</blockquote><div><br></div><div>As you can see, all current use cases are =
expanded by adding a comma between each expanded elements.</div><div><br></=
div><div>One of the things Richard suggested in this thread was adding a ne=
w meaning to the unpack operator when it is followed by a semicolon. It wou=
ld be expanded into several expression statement.</div>
<div><br></div></div></blockquote><div>It wouldn't even be necessary to=
change the simple and uniform way to expand a pack you mention. If instead=
of being expanded into several expression statements, it was expanded into=
a single comma-separated expression, it would still work, since operands t=
o the comma operator are always evaluated left-to right. It would of course=
behave differently if the comma operator is overloaded for the result type=
, but if you overloaded the comma operator, that's probably what you wa=
nt.</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><d=
iv>Now about the problem you are trying to solve with the current standard,=
just convert your 'do_nothing' function to a class instead and cal=
l its constructor using list-initialization:</div>
<div>
<br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><=
font face=3D"courier new, monospace">do_nothing{(str +=3D to_string(args)).=
...};</font></blockquote><div><br></div></div></blockquote><div>That's g=
reat... the only drawback of this (apart from being more verbose) is that i=
t doesn't work when the result of the expression is of type void, while=
the operands of the comma operator can both be of type void.</div>
<div>I guess a workaround would be:</div><div><br></div><div>=A0 =A0 do_not=
hing{ (func_returning_void(args), 0)... };</div><div><br></div><div>but it&=
#39;s getting a bit loaded on workarounds.</div><div>=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex">
<div dir=3D"ltr"><div></div><div>This is guaranteed to be evaluated left to=
right (note that Richard did talk about something like this in the current=
thread when he was referring to a class named 'sink'). But of cour=
se, it would be nicer if this workaround wasn't needed.</div>
<div><br></div><div>You can even expand over several statements using a lam=
bda:</div><div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none=
;padding:0px"><div><font face=3D"courier new, monospace">do_nothing{[&]=
() {</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 str +=3D to_string(args)=
;</font></div><div><font face=3D"courier new, monospace">=A0 =A0 str +=3D s=
eparator;</font></div><div><font face=3D"courier new, monospace">}() ...};<=
/font></div></blockquote>
<div><br></div><div>I saw someone in another thread propose expanding packs=
in a for-range fashion (using a 'for...' syntax):</div><div><br></=
div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>
<font face=3D"courier new, monospace">for... (const auto& a : args) {</=
font></div><div><font face=3D"courier new, monospace">=A0 =A0 str +=3D to_s=
tring(a);</font></div><div><font face=3D"courier new, monospace">=A0 =A0 st=
r +=3D separator;</font></div>
<div><font face=3D"courier new, monospace">}</font></div></blockquote><div>=
<br></div><div>I like this idea a lot, but I'm not sure the one who pro=
posed it will go forward with it.</div><div><br></div><div>Something simila=
r can currently be done if we expand all elements into an initializer list:=
</div>
<div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0=
px"><div><font face=3D"courier new, monospace">for (const auto& a : { t=
o_string(args)... })=A0{</font></div><div><font face=3D"courier new, monosp=
ace">=A0 =A0 str +=3D a;</font></div>
<div><font face=3D"courier new, monospace">=A0 =A0 str +=3D separator;</fon=
t></div><div><font face=3D"courier new, monospace">}</font></div></blockquo=
te><div><br></div><div>It works in this example but requires that all eleme=
nts are expanded to a single type. It is not always wanted or even possible=
to convert all elements to a single type.</div>
</div><div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote"><div><d=
iv class=3D"h5">On Fri, Dec 6, 2013 at 7:29 AM, Xavi Gratal <span dir=3D"lt=
r"><<a href=3D"mailto:gratal@gmail.com" target=3D"_blank">gratal@gmail.c=
om</a>></span> wrote:<br>
</div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"h5">
<div dir=3D"ltr">On a related note, why is parameter pack expansion only al=
lowed in the context of a function call?<div>I have the following code:</di=
v><div><br></div><div><div style=3D"background-color:rgb(250,250,250);borde=
r:1px solid rgb(187,187,187);word-wrap:break-word">
<code><div><span style=3D"color:#008">const</span><span> std</span><span st=
yle=3D"color:#660">::</span><span style=3D"color:#008">string</span><span> =
</span><span style=3D"color:#660">&</span><span>to_string</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span> s=
td</span><span style=3D"color:#660">::</span><span style=3D"color:#008">str=
ing</span><span> </span><span style=3D"color:#660">&</span><span>str</s=
pan><span style=3D"color:#660">)</span><span> </span><span style=3D"color:#=
660">{</span><span> </span><span style=3D"color:#008">return</span><span> s=
tr</span><span style=3D"color:#660">;</span><span> </span><span style=3D"co=
lor:#660">}</span><span><br>
<br></span><span style=3D"color:#008">void</span><span> do_concat</span><sp=
an style=3D"color:#660">(</span><span>std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#008">string</span><span style=3D"color:#660"=
>&)</span><span> </span><span style=3D"color:#660">{}</span><span><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span> rest_t</span><span style=3D"color:#660">></sp=
an><span><br>
</span><span style=3D"color:#008">void</span><span> do_concat</span><span s=
tyle=3D"color:#660">(</span><span>std</span><span style=3D"color:#660">::</=
span><span style=3D"color:#008">string</span><span> </span><span style=3D"c=
olor:#660">&</span><span>str</span><span style=3D"color:#660">,</span><=
span style=3D"color:#008">const</span><span> std</span><span style=3D"color=
:#660">::</span><span style=3D"color:#008">string</span><span> </span><span=
style=3D"color:#660">&</span><span style=3D"color:#008">next</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#008">const</span><spa=
n> rest_t</span><span style=3D"color:#660">&...</span><span> rest</span=
><span style=3D"color:#660">)</span><span> </span><span style=3D"color:#660=
">{</span><span><br>
=A0 =A0 str</span><span style=3D"color:#660">+=3D</span><span style=3D"colo=
r:#008">next</span><span style=3D"color:#660">;</span><span><br>=A0 =A0 do_=
concat</span><span style=3D"color:#660">(</span><span>str</span><span style=
=3D"color:#660">,</span><span>rest</span><span style=3D"color:#660">...);</=
span><span><br>
</span><span style=3D"color:#660">}</span><span><br><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">typename</span><span style=3D"color:#660">...</span><s=
pan> args_t</span><span style=3D"color:#660">></span><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span> std</span><spa=
n style=3D"color:#660">::</span><span>to_string</span><span style=3D"color:=
#660">;</span><span><br>=A0 =A0 </span><span style=3D"color:#008">using</sp=
an><span> </span><span style=3D"color:#660">::</span><span>to_string</span>=
<span style=3D"color:#660">;</span><span><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span> str</span><span style=3D"color:#660">;</span>=
<span><br>=A0 =A0 do_concat</span><span style=3D"color:#660">(</span><span>=
str</span><span style=3D"color:#660">,</span><span>to_string</span><span st=
yle=3D"color:#660">(</span><span>args</span><span style=3D"color:#660">)...=
);</span><span><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span> str</span><sp=
an style=3D"color:#660">;</span><span><br></span><span style=3D"color:#660"=
>}</span><span><br><br></span><span style=3D"color:#008">int</span><span> m=
ain</span><span style=3D"color:#660">()</span><span><br>
</span><span style=3D"color:#660">{</span><span><br>=A0 =A0 std</span><span=
style=3D"color:#660">::</span><span>cout </span><span style=3D"color:#660"=
><<</span><span> make_string</span><span style=3D"color:#660">(</span=
><span style=3D"color:#080">"aaa "</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#066">1</span><span style=3D"color:#660">,<=
/span><span style=3D"color:#080">" bbb "</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#066">1.3</span><span style=3D"color:=
#660">)</span><span> </span><span style=3D"color:#660"><<</span><span=
> </span><span style=3D"color:#080">"\n"</span><span style=3D"col=
or:#660">;</span><span><br>
</span><span style=3D"color:#660">}</span><span><br></span></div></code></d=
iv><div><br></div><div>Which works fine, but if we allowed parameter pack s=
tatement expansion, make_string could be implemented as:</div><div>
<br></div><div style=3D"background-color:rgb(250,250,250);border:1px solid =
rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"color:#008=
">template</span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#660">...</span><span> args_t</s=
pan><span style=3D"color:#660">></span><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span> std</span><spa=
n style=3D"color:#660">::</span><span>to_string</span><span style=3D"color:=
#660">;</span><span><br>=A0 =A0 </span><span style=3D"color:#008">using</sp=
an><span> </span><span style=3D"color:#660">::</span><span>to_string</span>=
<span style=3D"color:#660">;</span><span><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span> str</span><span style=3D"color:#660">;</span>=
<span><br>=A0 =A0 </span><span style=3D"color:#660">(</span><span>str</span=
><span style=3D"color:#660">+=3D</span><span>to_string</span><span style=3D=
"color:#660">(</span><span>args</span><span style=3D"color:#660">))...;</sp=
an><span><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span> str</span><sp=
an style=3D"color:#660">;</span><span><br></span><span style=3D"color:#660"=
>}</span><span><br></span></div></code></div><div><br></div>and do_concat w=
ould no longer be necessary. It is almost possible to do it with:</div>
<div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);backgro=
und-color:rgb(250,250,250);word-wrap:break-word"><code><div><span style=3D"=
color:#008">template</span><span style=3D"color:#660"><</span><span styl=
e=3D"color:#008">typename</span><span style=3D"color:#660">...</span><span>=
args_t</span><span style=3D"color:#660">></span><span> do_nothing</span=
><span style=3D"color:#660">(</span><span style=3D"color:#008">const</span>=
<span> args_t</span><span style=3D"color:#660">&...</span><span> args</=
span><span style=3D"color:#660">)</span><span> </span><span style=3D"color:=
#660">{}</span><span><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span> args_t</span><span style=3D"color:#660">></sp=
an><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
=A0 =A0 </span><span style=3D"color:#008">using</span><span> std</span><spa=
n style=3D"color:#660">::</span><span>to_string</span><span style=3D"color:=
#660">;</span><span><br>=A0 =A0 </span><span style=3D"color:#008">using</sp=
an><span> </span><span style=3D"color:#660">::</span><span>to_string</span>=
<span style=3D"color:#660">;</span><span><br>
<br>=A0 =A0 std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#008">string</span><span> str</span><span style=3D"color:#660">;</span>=
<span><br>=A0 =A0 do_nothing</span><span style=3D"color:#660">((</span><spa=
n>str</span><span style=3D"color:#660">+=3D</span><span>to_string</span><sp=
an style=3D"color:#660">(</span><span>args</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#660">)...);</span><span><br>
=A0 =A0 </span><span style=3D"color:#008">return</span><span> str</span><sp=
an style=3D"color:#660">;</span><span><br></span><span style=3D"color:#660"=
>}</span><span><br></span></div></code></div><div><br></div><div>
except that the result is not the expected one, since the arguments to do_n=
othing are evaluated in arbitrary order.</div><div><br></div><div>Was there=
any specific reason to disallow expansion outside of a function call? Is t=
here any simpler way to implement make_string?</div>
</div><div><br></div></div></div></div><div><div><span class=3D"HOEnZb"><fo=
nt color=3D"#888888">
<p></p>
-- <br>
=A0<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ=
/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D"_blank">std-pr=
oposals+unsubscribe@isocpp.org</a>.</font></span><div class=3D"im"><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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></div></blockquote></div><br></div><div class=3D"HOEnZb"><div c=
lass=3D"h5">
<p></p>
-- <br>
=A0<br>
--- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01536a84eb65a104ecdf3a8c--
.
Author: Xeo <hivemaster@hotmail.de>
Date: Fri, 6 Dec 2013 07:42:53 -0800 (PST)
Raw View
------=_Part_755_20529653.1386344573955
Content-Type: text/plain; charset=ISO-8859-1
That is actually the now common idiom to expand packs whereever.
namespace detail{
// array alias, since GCC doesn't correctly support LTR evaluation for
structs / classes
using swallow = int[];
} // detail::
// extra 0 at front since 0-sized arrays aren't permitted
// void() in the middle to suppress overloaded comma-operators
// 0 at end to get a uniform type
#define VARIADIC_EXPAND(expr) detail::swallow{ 0, ((expr), void(), 0)... }
And then
VARIADIC_EXPAND( str += to_string(args) );
On Friday, December 6, 2013 4:23:37 PM UTC+1, Xavi Gratal wrote:
>
> Thanks a lot for the explanation!
>
>
> 2013/12/6 Alex B <deva...@gmail.com <javascript:>>
>
>> I guess the reason is to initially make it simple and uniform to expand a
>> pack. Right now, the equivalent of a pack expansion is as simple as
>> separating each elements of the pack by a comma and nothing else. Note that
>> current rules do not only allow to expand in function call but in other
>> contexts as well.
>>
>> Here is one example:
>>
>> template <class... Bases>
>> class Derived : public Bases...
>> {};
>>
>>
>> And another one:
>>
>> template <int... Values>
>> void f()
>> {
>> int values[] = { Values... };
>> }
>>
>>
>> As you can see, all current use cases are expanded by adding a comma
>> between each expanded elements.
>>
>> One of the things Richard suggested in this thread was adding a new
>> meaning to the unpack operator when it is followed by a semicolon. It would
>> be expanded into several expression statement.
>>
>> It wouldn't even be necessary to change the simple and uniform way to
> expand a pack you mention. If instead of being expanded into several
> expression statements, it was expanded into a single comma-separated
> expression, it would still work, since operands to the comma operator are
> always evaluated left-to right. It would of course behave differently if
> the comma operator is overloaded for the result type, but if you overloaded
> the comma operator, that's probably what you want.
>
>
>> Now about the problem you are trying to solve with the current standard,
>> just convert your 'do_nothing' function to a class instead and call its
>> constructor using list-initialization:
>>
>> do_nothing{(str += to_string(args))...};
>>
>>
>> That's great... the only drawback of this (apart from being more verbose)
> is that it doesn't work when the result of the expression is of type void,
> while the operands of the comma operator can both be of type void.
> I guess a workaround would be:
>
> do_nothing{ (func_returning_void(args), 0)... };
>
> but it's getting a bit loaded on workarounds.
>
>
>> This is guaranteed to be evaluated left to right (note that Richard did
>> talk about something like this in the current thread when he was referring
>> to a class named 'sink'). But of course, it would be nicer if this
>> workaround wasn't needed.
>>
>> You can even expand over several statements using a lambda:
>>
>> do_nothing{[&]() {
>> str += to_string(args);
>> str += separator;
>> }() ...};
>>
>>
>> I saw someone in another thread propose expanding packs in a for-range
>> fashion (using a 'for...' syntax):
>>
>> for... (const auto& a : args) {
>> str += to_string(a);
>> str += separator;
>> }
>>
>>
>> I like this idea a lot, but I'm not sure the one who proposed it will go
>> forward with it.
>>
>> Something similar can currently be done if we expand all elements into an
>> initializer list:
>>
>> for (const auto& a : { to_string(args)... }) {
>> str += a;
>> str += separator;
>> }
>>
>>
>> It works in this example but requires that all elements are expanded to a
>> single type. It is not always wanted or even possible to convert all
>> elements to a single type.
>>
>>
>> On Fri, Dec 6, 2013 at 7:29 AM, Xavi Gratal <gra...@gmail.com<javascript:>
>> > wrote:
>>
>>> On a related note, why is parameter pack expansion only allowed in the
>>> context of a function call?
>>> I have the following code:
>>>
>>> const std::string &to_string(const std::string &str) { return str; }
>>>
>>> void do_concat(std::string&) {}
>>>
>>> template<typename... rest_t>
>>> void do_concat(std::string &str,const std::string &next,const rest_t&...rest
>>> ) {
>>> str+=next;
>>> do_concat(str,rest...);
>>> }
>>>
>>> template<typename... args_t>
>>> std::string make_string(const args_t&... args) {
>>> using std::to_string;
>>> using ::to_string;
>>>
>>> std::string str;
>>> do_concat(str,to_string(args)...);
>>> return str;
>>> }
>>>
>>> int main()
>>> {
>>> std::cout << make_string("aaa ",1," bbb ",1.3) << "\n";
>>> }
>>>
>>> Which works fine, but if we allowed parameter pack statement expansion,
>>> make_string could be implemented as:
>>>
>>> template<typename... args_t>
>>> std::string make_string(const args_t&... args) {
>>> using std::to_string;
>>> using ::to_string;
>>>
>>> std::string str;
>>> (str+=to_string(args))...;
>>> return str;
>>> }
>>>
>>> and do_concat would no longer be necessary. It is almost possible to do
>>> it with:
>>>
>>> template<typename... args_t> do_nothing(const args_t&... args) {}
>>>
>>> template<typename... args_t>
>>> std::string make_string(const args_t&... args) {
>>> using std::to_string;
>>> using ::to_string;
>>>
>>> std::string str;
>>> do_nothing((str+=to_string(args))...);
>>> return str;
>>> }
>>>
>>> except that the result is not the expected one, since the arguments to
>>> do_nothing are evaluated in arbitrary order.
>>>
>>> Was there any specific reason to disallow expansion outside of a
>>> function call? Is there any simpler way to implement make_string?
>>>
>>> --
>>>
>>> ---
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "ISO C++ Standard - Future Proposals" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe
>>> .
>>> To unsubscribe from this group and all its topics, send an email to
>>> std-proposal...@isocpp.org <javascript:>.
>>>
>>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>>> Visit this group at
>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>
>>
>> --
>>
>> ---
>> 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:>.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>
--
---
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/.
------=_Part_755_20529653.1386344573955
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">That is actually the now common idiom to expand packs wher=
eever.<br><br><div class=3D"prettyprint" 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"color: #008;" class=3D"styled-by-prettif=
y">namespace</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> detail</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"></span><br=
><code class=3D"prettyprint"><span style=3D"color: #800;" class=3D"styled-b=
y-prettify">// array alias, since GCC doesn't correctly support LTR evaluat=
ion for structs / classes</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span></code><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">using</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> swallow </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">[];</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></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: #800;=
" class=3D"styled-by-prettify">// detail::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br><br>// extra 0 at front since 0-sized a=
rrays aren't permitted<br>// void() in the middle to suppress overloaded co=
mma-operators<br>// 0 at end to get a uniform type<br></span><span style=3D=
"color: #800;" class=3D"styled-by-prettify">#define</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> VARIADIC_EXPAND</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">expr</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> detail</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">swallow</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: #066;" class=3D"styled-by-prettify">0</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">((</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">expr</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">),</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> void(), </span><span style=3D"color: #066;" class=3D"sty=
led-by-prettify">0</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">)...</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></span></div=
></code></div><br>And then<br><br><div class=3D"prettyprint" style=3D"backg=
round-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-s=
tyle: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify">VARIADIC_EXPAND</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> str </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> to_string</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</spa=
n> );<br></div></code></div><br>On Friday, December 6, 2013 4:23:37 PM UTC+=
1, Xavi Gratal wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">Thanks a lot for the explanation!<br><div><br><br><div class=3D"gm=
ail_quote">2013/12/6 Alex B <span dir=3D"ltr"><<a href=3D"javascript:" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"fnLNCUziCPIJ" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">deva...@gmail.com</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">I guess the reason is to in=
itially make it simple and uniform to expand a pack. Right now, the equival=
ent of a pack expansion is as simple as separating each elements of the pac=
k by a comma and nothing else. Note that current rules do not only allow to=
expand in function call but in other contexts as well.<div>
<br></div><div>Here is one example:</div><div><br></div><blockquote style=
=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"cou=
rier new, monospace">template <class... Bases></font></div><div><font=
face=3D"courier new, monospace">class Derived : public Bases...</font></di=
v>
<div><font face=3D"courier new, monospace">{};</font></div></blockquote><di=
v><br></div><div>And another one:</div><div><br></div><blockquote style=3D"=
margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"courier=
new, monospace">template <int... Values></font></div>
<div><font face=3D"courier new, monospace">void f()</font></div><div><font =
face=3D"courier new, monospace">{</font></div><div><font face=3D"courier ne=
w, monospace"> int values[] =3D { Values... };</font></div><di=
v><font face=3D"courier new, monospace">}</font></div>
</blockquote><div><br></div><div>As you can see, all current use cases are =
expanded by adding a comma between each expanded elements.</div><div><br></=
div><div>One of the things Richard suggested in this thread was adding a ne=
w meaning to the unpack operator when it is followed by a semicolon. It wou=
ld be expanded into several expression statement.</div>
<div><br></div></div></blockquote><div>It wouldn't even be necessary to cha=
nge the simple and uniform way to expand a pack you mention. If instead of =
being expanded into several expression statements, it was expanded into a s=
ingle comma-separated expression, it would still work, since operands to th=
e comma operator are always evaluated left-to right. It would of course beh=
ave differently if the comma operator is overloaded for the result type, bu=
t if you overloaded the comma operator, that's probably what you want.</div=
>
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div=
><div>Now about the problem you are trying to solve with the current standa=
rd, just convert your 'do_nothing' function to a class instead and call its=
constructor using list-initialization:</div>
<div>
<br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><=
font face=3D"courier new, monospace">do_nothing{(str +=3D to_string(args)).=
...};</font></blockquote><div><br></div></div></blockquote><div>That's great=
.... the only drawback of this (apart from being more verbose) is that it do=
esn't work when the result of the expression is of type void, while the ope=
rands of the comma operator can both be of type void.</div>
<div>I guess a workaround would be:</div><div><br></div><div> =
do_nothing{ (func_returning_void(args), 0)... };</div><div><br></div><div>b=
ut it's getting a bit loaded on workarounds.</div><div> </div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex">
<div dir=3D"ltr"><div></div><div>This is guaranteed to be evaluated left to=
right (note that Richard did talk about something like this in the current=
thread when he was referring to a class named 'sink'). But of course, it w=
ould be nicer if this workaround wasn't needed.</div>
<div><br></div><div>You can even expand over several statements using a lam=
bda:</div><div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none=
;padding:0px"><div><font face=3D"courier new, monospace">do_nothing{[&]=
() {</font></div>
<div><font face=3D"courier new, monospace"> str +=3D to_string=
(args);</font></div><div><font face=3D"courier new, monospace">  =
; str +=3D separator;</font></div><div><font face=3D"courier new, monospace=
">}() ...};</font></div></blockquote>
<div><br></div><div>I saw someone in another thread propose expanding packs=
in a for-range fashion (using a 'for...' syntax):</div><div><br></div><blo=
ckquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>
<font face=3D"courier new, monospace">for... (const auto& a : args) {</=
font></div><div><font face=3D"courier new, monospace"> str +=
=3D to_string(a);</font></div><div><font face=3D"courier new, monospace">&n=
bsp; str +=3D separator;</font></div>
<div><font face=3D"courier new, monospace">}</font></div></blockquote><div>=
<br></div><div>I like this idea a lot, but I'm not sure the one who propose=
d it will go forward with it.</div><div><br></div><div>Something similar ca=
n currently be done if we expand all elements into an initializer list:</di=
v>
<div><br></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0=
px"><div><font face=3D"courier new, monospace">for (const auto& a : { t=
o_string(args)... }) {</font></div><div><font face=3D"courier new, mon=
ospace"> str +=3D a;</font></div>
<div><font face=3D"courier new, monospace"> str +=3D separator=
;</font></div><div><font face=3D"courier new, monospace">}</font></div></bl=
ockquote><div><br></div><div>It works in this example but requires that all=
elements are expanded to a single type. It is not always wanted or even po=
ssible to convert all elements to a single type.</div>
</div><div><br><br><div class=3D"gmail_quote"><div><div>On Fri, Dec 6, 2013=
at 7:29 AM, Xavi Gratal <span dir=3D"ltr"><<a href=3D"javascript:" targ=
et=3D"_blank" gdf-obfuscated-mailto=3D"fnLNCUziCPIJ" onmousedown=3D"this.hr=
ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';retur=
n true;">gra...@gmail.com</a>></span> wrote:<br>
</div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div><div>
<div dir=3D"ltr">On a related note, why is parameter pack expansion only al=
lowed in the context of a function call?<div>I have the following code:</di=
v><div><br></div><div><div style=3D"background-color:rgb(250,250,250);borde=
r:1px solid rgb(187,187,187);word-wrap:break-word">
<code><div><span style=3D"color:#008">const</span><span> std</span><span st=
yle=3D"color:#660">::</span><span style=3D"color:#008">string</span><span> =
</span><span style=3D"color:#660">&</span><span>to_string</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span> s=
td</span><span style=3D"color:#660">::</span><span style=3D"color:#008">str=
ing</span><span> </span><span style=3D"color:#660">&</span><span>str</s=
pan><span style=3D"color:#660">)</span><span> </span><span style=3D"color:#=
660">{</span><span> </span><span style=3D"color:#008">return</span><span> s=
tr</span><span style=3D"color:#660">;</span><span> </span><span style=3D"co=
lor:#660">}</span><span><br>
<br></span><span style=3D"color:#008">void</span><span> do_concat</span><sp=
an style=3D"color:#660">(</span><span>std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#008">string</span><span style=3D"color:#660"=
>&)</span><span> </span><span style=3D"color:#660">{}</span><span><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span> rest_t</span><span style=3D"color:#660">></sp=
an><span><br>
</span><span style=3D"color:#008">void</span><span> do_concat</span><span s=
tyle=3D"color:#660">(</span><span>std</span><span style=3D"color:#660">::</=
span><span style=3D"color:#008">string</span><span> </span><span style=3D"c=
olor:#660">&</span><span>str</span><span style=3D"color:#660">,</span><=
span style=3D"color:#008">const</span><span> std</span><span style=3D"color=
:#660">::</span><span style=3D"color:#008">string</span><span> </span><span=
style=3D"color:#660">&</span><span style=3D"color:#008">next</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#008">const</span><spa=
n> rest_t</span><span style=3D"color:#660">&...</span><span> rest</span=
><span style=3D"color:#660">)</span><span> </span><span style=3D"color:#660=
">{</span><span><br>
str</span><span style=3D"color:#660">+=3D</span><span style=
=3D"color:#008">next</span><span style=3D"color:#660">;</span><span><br>&nb=
sp; do_concat</span><span style=3D"color:#660">(</span><span>str</sp=
an><span style=3D"color:#660">,</span><span>rest</span><span style=3D"color=
:#660">...);</span><span><br>
</span><span style=3D"color:#660">}</span><span><br><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">typename</span><span style=3D"color:#660">...</span><s=
pan> args_t</span><span style=3D"color:#660">></span><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
</span><span style=3D"color:#008">using</span><span> std</spa=
n><span style=3D"color:#660">::</span><span>to_string</span><span style=3D"=
color:#660">;</span><span><br> </span><span style=3D"color:#00=
8">using</span><span> </span><span style=3D"color:#660">::</span><span>to_s=
tring</span><span style=3D"color:#660">;</span><span><br>
<br> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">string</span><span> str</span><span style=3D"color:#660">;<=
/span><span><br> do_concat</span><span style=3D"color:#660">(<=
/span><span>str</span><span style=3D"color:#660">,</span><span>to_string</s=
pan><span style=3D"color:#660">(</span><span>args</span><span style=3D"colo=
r:#660">).<wbr>..);</span><span><br>
</span><span style=3D"color:#008">return</span><span> str</sp=
an><span style=3D"color:#660">;</span><span><br></span><span style=3D"color=
:#660">}</span><span><br><br></span><span style=3D"color:#008">int</span><s=
pan> main</span><span style=3D"color:#660">()</span><span><br>
</span><span style=3D"color:#660">{</span><span><br> std</span=
><span style=3D"color:#660">::</span><span>cout </span><span style=3D"color=
:#660"><<</span><span> make_string</span><span style=3D"color:#660">(=
</span><span style=3D"color:#080">"aaa "</span><span style=3D"color:#660">,=
</span><span style=3D"color:#066">1</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#080">" bbb "</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#066">1.3</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660"><<</span><span> </span><span=
style=3D"color:#080">"\n"</span><span style=3D"color:#660">;</span><span><=
br>
</span><span style=3D"color:#660">}</span><span><br></span></div></code></d=
iv><div><br></div><div>Which works fine, but if we allowed parameter pack s=
tatement expansion, make_string could be implemented as:</div><div>
<br></div><div style=3D"background-color:rgb(250,250,250);border:1px solid =
rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"color:#008=
">template</span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#660">...</span><span> args_t</s=
pan><span style=3D"color:#660">></span><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
</span><span style=3D"color:#008">using</span><span> std</spa=
n><span style=3D"color:#660">::</span><span>to_string</span><span style=3D"=
color:#660">;</span><span><br> </span><span style=3D"color:#00=
8">using</span><span> </span><span style=3D"color:#660">::</span><span>to_s=
tring</span><span style=3D"color:#660">;</span><span><br>
<br> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">string</span><span> str</span><span style=3D"color:#660">;<=
/span><span><br> </span><span style=3D"color:#660">(</span><sp=
an>str</span><span style=3D"color:#660">+=3D</span><span>to_string</span><s=
pan style=3D"color:#660">(</span><span>args</span><span style=3D"color:#660=
">))...;</span><span><br>
</span><span style=3D"color:#008">return</span><span> str</sp=
an><span style=3D"color:#660">;</span><span><br></span><span style=3D"color=
:#660">}</span><span><br></span></div></code></div><div><br></div>and do_co=
ncat would no longer be necessary. It is almost possible to do it with:</di=
v>
<div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);backgro=
und-color:rgb(250,250,250);word-wrap:break-word"><code><div><span style=3D"=
color:#008">template</span><span style=3D"color:#660"><</span><span styl=
e=3D"color:#008">typename</span><span style=3D"color:#660">...</span><span>=
args_t</span><span style=3D"color:#660">></span><span> do_nothing</span=
><span style=3D"color:#660">(</span><span style=3D"color:#008">const</span>=
<span> args_t</span><span style=3D"color:#660">&...</span><span> args</=
span><span style=3D"color:#660">)</span><span> </span><span style=3D"color:=
#660">{}</span><span><br>
<br></span><span style=3D"color:#008">template</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">typename</span><span style=3D"co=
lor:#660">...</span><span> args_t</span><span style=3D"color:#660">></sp=
an><span><br>
std</span><span style=3D"color:#660">::</span><span style=3D"color:#008">st=
ring</span><span> make_string</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span> args_t</span><span style=3D"color=
:#660">&...</span><span> args</span><span style=3D"color:#660">)</span>=
<span> </span><span style=3D"color:#660">{</span><span><br>
</span><span style=3D"color:#008">using</span><span> std</spa=
n><span style=3D"color:#660">::</span><span>to_string</span><span style=3D"=
color:#660">;</span><span><br> </span><span style=3D"color:#00=
8">using</span><span> </span><span style=3D"color:#660">::</span><span>to_s=
tring</span><span style=3D"color:#660">;</span><span><br>
<br> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">string</span><span> str</span><span style=3D"color:#660">;<=
/span><span><br> do_nothing</span><span style=3D"color:#660">(=
(</span><span>str</span><span style=3D"color:#660">+=3D</span><span>to_stri=
ng</span><span style=3D"color:#660">(</span><span>arg<wbr>s</span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#660">)...);</span><span><br=
>
</span><span style=3D"color:#008">return</span><span> str</sp=
an><span style=3D"color:#660">;</span><span><br></span><span style=3D"color=
:#660">}</span><span><br></span></div></code></div><div><br></div><div>
except that the result is not the expected one, since the arguments to do_n=
othing are evaluated in arbitrary order.</div><div><br></div><div>Was there=
any specific reason to disallow expansion outside of a function call? Is t=
here any simpler way to implement make_string?</div>
</div><div><br></div></div></div></div><div><div><span><font color=3D"#8888=
88">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/YkHPCYb-KPQ/unsubscribe" target=3D"_blan=
k" onmousedown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/top=
ic/std-proposals/YkHPCYb-KPQ/unsubscribe';return true;" onclick=3D"this.hre=
f=3D'https://groups.google.com/a/isocpp.org/d/topic/std-proposals/YkHPCYb-K=
PQ/unsubscribe';return true;">https://groups.google.com/a/<wbr>isocpp.org/d=
/topic/std-<wbr>proposals/YkHPCYb-KPQ/<wbr>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"fnLNCUziCPIJ" o=
nmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.org</a>.</font><=
/span><div><br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"fnLNCUziCPIJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</div></div></div></blockquote></div><br></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "=
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"=
fnLNCUziCPIJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.or=
g</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"fnLNCUziCPIJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</div></div></blockquote></div><br></div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_755_20529653.1386344573955--
.
Author: Alex B <devalexb@gmail.com>
Date: Mon, 9 Dec 2013 14:26:29 -0500
Raw View
--089e013c664009e6f104ed1ef9e8
Content-Type: text/plain; charset=ISO-8859-1
Hi Richard,
I am thinking a bit more about your proposal and have a few questions.
1.
Consider the following code:
template <class... T>
struct A
{
using data_types = types<T...>;
T operator...() const;
/*...*/
};
template <class AType> // AType is supposed to be a type with the same
interface as A
struct B
{
using data_types = types<*typename ...*AType::data_types...>;
std::tuple<...data_types...> _data;
B(...data_types... d) : _data(d...) {}
B(const AType& a) : B(...a...) {}
};
Q: Is the underlined typename required in your proposal? Or does the
ellipsis prefix removes the need for it in that context?
(also please feel free to correct any other mistake I may have made)
2.
(answer to this one might alter answer to first)
Did you think about static operator... ?
template <int... I>
struct int_seq
{
static decltype(I) operator...() { return I; }
};
using seq = int_seq<0, 1, 2, 3, 4>;
using seq2 = int_seq<...seq * 2 ...>; // 0, 2, 4, 6, 8
If this is allowed, this would make typename in my first example required.
3.
You propose two (three?) packification syntax:
- using ... =
- operator...
- (static operator...)
Would a class be allowed to define more than one of these?
4.
Consider the following code:
struct A { using Y = int; };
struct B { using Y = char; };
struct X {
using ... = ...types<A, B>;
struct Y {
using ... = ...types<float, double>;
};
};
void f(...X::Y...);
The definition of f looks ambiguous to me; it is not clear if the ...
prefix applies to X or Y. Is it equivalent to
void f(int, char);
or
void f(float, double);
?
--
---
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/.
--089e013c664009e6f104ed1ef9e8
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Richard,<div><br></div><div>I am thinking a bit more ab=
out your proposal and have a few questions.</div><div><br></div><div>1.</di=
v><div>Consider the following code:</div><div><div><font face=3D"courier ne=
w, monospace">template <class... T></font></div>
<div><font face=3D"courier new, monospace">struct A</font></div><div><font =
face=3D"courier new, monospace">{</font></div><div><font face=3D"courier ne=
w, monospace"><span style=3D"white-space:pre-wrap"> </span>using data_types=
=3D types<T...>;</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </span>T =
operator...() const;</font></div><div><font face=3D"courier new, monospace"=
><br>
</font></div><div><font face=3D"courier new, monospace"><span style=3D"whit=
e-space:pre-wrap"> </span>/*...*/</font></div><div><font face=3D"courier ne=
w, monospace">};</font></div><div><font face=3D"courier new, monospace"><br=
>
</font></div><div><font face=3D"courier new, monospace">template <class =
AType> // AType is supposed to be a type with the same interface as A</f=
ont></div><div><font face=3D"courier new, monospace">struct B</font></div>
<div>
<font face=3D"courier new, monospace">{</font></div><div><font face=3D"cour=
ier new, monospace"><span style=3D"white-space:pre-wrap"> </span>using data=
_types =3D types<<b><u>typename</u>=A0...</b>AType::data_types...>;</=
font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </span>st=
d::tuple<...data_types...> _data;</font></div><div><span style=3D"whi=
te-space:pre-wrap"><font face=3D"courier new, monospace"> </font></span></d=
iv>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>B(...data_types... d) : _data(d...) {}</font></div><div><font =
face=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </spa=
n>B(const AType& a) : B(...a...) {}</font></div>
<div><font face=3D"courier new, monospace">};</font></div></div><div><br></=
div><div>Q: Is the underlined typename required in your proposal? Or does t=
he ellipsis prefix removes the need for it in that context?</div><div>(also=
please feel free to correct any other mistake I may have made)</div>
<div><br></div><div><br></div><div>2.</div><div>(answer to this one might a=
lter answer to first)</div><div><br></div><div>Did you think about static o=
perator... ?</div><div><br></div><blockquote style=3D"margin:0px 0px 0px 40=
px;border:none;padding:0px">
<div><font face=3D"courier new, monospace">template <int... I></font>=
</div><div><font face=3D"courier new, monospace">
struct int_seq</font></div><div><font face=3D"courier new, monospace">{</fo=
nt></div><div><font face=3D"courier new, monospace">=A0 =A0 static decltype=
(I) operator...() { return I; }</font></div><div><font face=3D"courier new,=
monospace">};</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">using seq =3D int_seq<0, 1, 2, 3, 4>;</fo=
nt></div><div><font face=3D"courier new, monospace">using seq2 =3D int_seq&=
lt;...seq * 2 ...>; // 0, 2, 4, 6, 8</font></div>
</blockquote>
<div><br></div><div>If this is allowed, this would make typename in my firs=
t example required.</div><div><br></div><div><br></div><div>3.</div><div>Yo=
u propose two (three?) packification syntax:</div><div>- using ... =3D</div=
>
<div>- operator...</div><div>- (static operator...)</div><div><br></div><di=
v>Would a class be allowed to define more than one of these?</div><div><br>=
</div><div><br></div><div>4.</div><div>Consider the following code:</div>
<div><br></div><blockquote style=3D"margin:0px 0px 0px 40px;border:none;pad=
ding:0px"><div><div><font face=3D"courier new, monospace">struct A { using =
Y =3D int; };</font></div></div></blockquote><blockquote style=3D"margin:0p=
x 0px 0px 40px;border:none;padding:0px">
<div><font face=3D"courier new, monospace">struct B { using Y =3D char; };<=
/font></div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;borde=
r:none;padding:0px"><div><div><font face=3D"courier new, monospace"><br></f=
ont></div>
<div><font face=3D"courier new, monospace">struct X {</font></div><div><fon=
t face=3D"courier new, monospace"><span class=3D"" style=3D"white-space:pre=
"> </span>using ... =3D ...types<A, B>;</font></div><div><span style=
=3D"font-family:'courier new',monospace;white-space:pre"> </span><s=
pan style=3D"font-family:'courier new',monospace">struct Y {</span>=
<br>
</div><div><font face=3D"courier new, monospace"><span class=3D"" style=3D"=
white-space:pre"> </span></font><span style=3D"font-family:'courier new=
',monospace;white-space:pre"> </span><span style=3D"font-family:'co=
urier new',monospace">using ... =3D ...types<float, double>;</spa=
n></div>
<div><span style=3D"font-family:'courier new',monospace;white-space=
:pre"> </span><span style=3D"font-family:'courier new',monospace">}=
;</span><font face=3D"courier new, monospace"><br></font></div><div><font f=
ace=3D"courier new, monospace">};</font></div>
</div><div><font face=3D"courier new, monospace"><br></font></div><div><fon=
t face=3D"courier new, monospace">void f(...X::Y...);</font></div></blockqu=
ote><div><br></div><div>The definition of f looks ambiguous to me; it is no=
t clear if the ... prefix applies to X or Y. Is it equivalent to</div>
<blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div>=
<font face=3D"courier new, monospace">void f(int, char);</font></div></bloc=
kquote><div>or</div><blockquote style=3D"margin:0px 0px 0px 40px;border:non=
e;padding:0px">
<div><font face=3D"courier new, monospace">void f(float, double);</font></d=
iv></blockquote><div>?</div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e013c664009e6f104ed1ef9e8--
.
Author: Richard Smith <richard@metafoo.co.uk>
Date: Mon, 9 Dec 2013 12:16:29 -0800
Raw View
--047d7b6723d6dbd86404ed1fabc2
Content-Type: text/plain; charset=ISO-8859-1
On Mon, Dec 9, 2013 at 11:26 AM, Alex B <devalexb@gmail.com> wrote:
> Hi Richard,
>
> I am thinking a bit more about your proposal and have a few questions.
>
> 1.
> Consider the following code:
> template <class... T>
> struct A
> {
> using data_types = types<T...>;
>
> T operator...() const;
>
> /*...*/
> };
>
> template <class AType> // AType is supposed to be a type with the same
> interface as A
> struct B
> {
> using data_types = types<*typename ...*AType::data_types...>;
>
> std::tuple<...data_types...> _data;
> B(...data_types... d) : _data(d...) {}
> B(const AType& a) : B(...a...) {}
> };
>
> Q: Is the underlined typename required in your proposal? Or does the
> ellipsis prefix removes the need for it in that context?
> (also please feel free to correct any other mistake I may have made)
>
First, a caveat: I've not thought about supporting prefix '...' for types
as much as I've thought about supporting it for values.
The 'typename' would be required here, to indicate that the complete
qualified-id names a type (pack). Consider:
...AType::static_tuple_data_member...
I'd previously been expecting the syntax for the above to be:
...typename AType::data_types...
for consistency with ... as a prefix operator on values, but you raise an
excellent point (implied here and made explicit in your question 4): we
could potentially want to turn any element of a nested name specifier into
a pack. That being the case, one possible way of writing this would be:
typename AType::...data_types
However, that introduces an ambiguity in the expression case. Is:
...AType::static_tuple_data_member...
packifying AType, or packifying its static data member?
2.
> (answer to this one might alter answer to first)
>
> Did you think about static operator... ?
>
> template <int... I>
> struct int_seq
> {
> static decltype(I) operator...() { return I; }
> };
>
> using seq = int_seq<0, 1, 2, 3, 4>;
> using seq2 = int_seq<...seq * 2 ...>; // 0, 2, 4, 6, 8
>
>
> If this is allowed, this would make typename in my first example required.
>
I've not thought about this. We don't allow this sort of thing for other
operators, though, so I don't know whether people would expect this to work
here.
constexpr auto seq = int_seq<0, 1, 2, 3, 4>();
constexpr auto seq2 = int_seq<...seq * 2 ...>();
.... or ...
using seq = int_seq<0, 1, 2, 3, 4>;
using seq2 = int_seq<...seq{} * 2 ...>;
.... seem nearly-as-good syntaxes for the same thing.
3.
> You propose two (three?) packification syntax:
> - using ... =
> - operator...
> - (static operator...)
>
> Would a class be allowed to define more than one of these?
>
Yes. "using ... = " would specify what happens when prefix ..." is applied
to the type, "operator..." would specify what happens when prefix "..." is
applied to a value of that type. I don't see a need for a restriction here,
since I don't think there is any ambiguity between these two.
> 4.
> Consider the following code:
>
> struct A { using Y = int; };
>
> struct B { using Y = char; };
>
>
> struct X {
> using ... = ...types<A, B>;
> struct Y {
> using ... = ...types<float, double>;
> };
> };
>
> void f(...X::Y...);
>
>
> The definition of f looks ambiguous to me; it is not clear if the ...
> prefix applies to X or Y. Is it equivalent to
>
> void f(int, char);
>
> or
>
> void f(float, double);
>
> ?
>
That's a great question. I was intending for it to mean the latter, but
that makes it really hard to express the former. I think your approach of
allowing member typedef packs solves this really nicely.
--
---
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/.
--047d7b6723d6dbd86404ed1fabc2
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On M=
on, Dec 9, 2013 at 11:26 AM, Alex B <span dir=3D"ltr"><<a href=3D"mailto=
:devalexb@gmail.com" target=3D"_blank">devalexb@gmail.com</a>></span> wr=
ote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style=
:solid;padding-left:1ex">
<div dir=3D"ltr">Hi Richard,<div><br></div><div>I am thinking a bit more ab=
out your proposal and have a few questions.</div><div><br></div><div>1.</di=
v><div>Consider the following code:</div><div><div><font face=3D"courier ne=
w, monospace">template <class... T></font></div>
<div><font face=3D"courier new, monospace">struct A</font></div><div><font =
face=3D"courier new, monospace">{</font></div><div><font face=3D"courier ne=
w, monospace"><span style=3D"white-space:pre-wrap"> </span>using data_types=
=3D types<T...>;</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </span>T =
operator...() const;</font></div><div><font face=3D"courier new, monospace"=
><br>
</font></div><div><font face=3D"courier new, monospace"><span style=3D"whit=
e-space:pre-wrap"> </span>/*...*/</font></div><div><font face=3D"courier ne=
w, monospace">};</font></div><div><font face=3D"courier new, monospace"><br=
>
</font></div><div><font face=3D"courier new, monospace">template <class =
AType> // AType is supposed to be a type with the same interface as A</f=
ont></div><div><font face=3D"courier new, monospace">struct B</font></div>
<div>
<font face=3D"courier new, monospace">{</font></div><div><font face=3D"cour=
ier new, monospace"><span style=3D"white-space:pre-wrap"> </span>using data=
_types =3D types<<b><u>typename</u>=A0...</b>AType::data_types...>;</=
font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </span>st=
d::tuple<...data_types...> _data;</font></div><div><span style=3D"whi=
te-space:pre-wrap"><font face=3D"courier new, monospace"> </font></span></d=
iv>
<div><font face=3D"courier new, monospace"><span style=3D"white-space:pre-w=
rap"> </span>B(...data_types... d) : _data(d...) {}</font></div><div><font =
face=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </spa=
n>B(const AType& a) : B(...a...) {}</font></div>
<div><font face=3D"courier new, monospace">};</font></div></div><div><br></=
div><div>Q: Is the underlined typename required in your proposal? Or does t=
he ellipsis prefix removes the need for it in that context?</div><div>(also=
please feel free to correct any other mistake I may have made)</div>
</div></blockquote><div><br></div><div>First, a caveat: I've not though=
t about supporting prefix '...' for types as much as I've thoug=
ht about supporting it for values.<br></div><div><div><br></div></div><div>
The 'typename' would be required here, to indicate that the complet=
e qualified-id names a type (pack). Consider:</div><div><br></div><div>=A0 =
....AType::static_tuple_data_member...</div><div><br></div><div>I'd prev=
iously been expecting the syntax for the above to be:</div>
<div><br></div><div>=A0 ...typename AType::data_types...</div><div><br></di=
v><div>for consistency with ... as a prefix operator on values, but you rai=
se an excellent point (implied here and made explicit in your question 4): =
we could potentially want to turn any element of a nested name specifier in=
to a pack. That being the case, one possible way of writing this would be:<=
/div>
<div><br></div><div>=A0 typename AType::...data_types</div><div><br></div><=
div>However, that introduces an ambiguity in the expression case. Is:</div>=
<div><br></div><div>=A0 ...AType::static_tuple_data_member...</div><div><br=
>
</div><div>packifying AType, or packifying its static data member?</div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex">
<div dir=3D"ltr"><div>2.</div><div>(answer to this one might alter answer t=
o first)</div><div><br></div><div>Did you think about static operator... ?<=
/div><div><br></div><blockquote style=3D"margin:0px 0px 0px 40px;border:non=
e;padding:0px">
<div><font face=3D"courier new, monospace">template <int... I></font>=
</div><div><font face=3D"courier new, monospace">
struct int_seq</font></div><div><font face=3D"courier new, monospace">{</fo=
nt></div><div><font face=3D"courier new, monospace">=A0 =A0 static decltype=
(I) operator...() { return I; }</font></div><div><font face=3D"courier new,=
monospace">};</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">using seq =3D int_seq<0, 1, 2, 3, 4>;</fo=
nt></div><div><font face=3D"courier new, monospace">using seq2 =3D int_seq&=
lt;...seq * 2 ...>; // 0, 2, 4, 6, 8</font></div>
</blockquote>
<div><br></div><div>If this is allowed, this would make typename in my firs=
t example required.</div></div></blockquote><div><br></div><div>I've no=
t thought about this. We don't allow this sort of thing for other opera=
tors, though, so I don't know whether people would expect this to work =
here.</div>
<div><br></div><div>=A0 constexpr auto seq =3D int_seq<0, 1, 2, 3, 4>=
();</div><div>=A0 constexpr auto seq2 =3D int_seq<...seq * 2 ...>();<=
/div><div><br></div><div>... or ...</div><div><br></div><div>=A0 using seq =
=3D int_seq<0, 1, 2, 3, 4>;</div>
<div>=A0 using seq2 =3D int_seq<...seq{} * 2 ...>;</div><div><br></di=
v><div>... seem nearly-as-good syntaxes for the same thing.</div><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex">
<div dir=3D"ltr"><div>3.</div><div>You propose two (three?) packification s=
yntax:</div><div>- using ... =3D</div>
<div>- operator...</div><div>- (static operator...)</div><div><br></div><di=
v>Would a class be allowed to define more than one of these?</div></div></b=
lockquote><div><br></div><div>Yes. "using ... =3D " would specify=
what happens when prefix ..." is applied to the type, "operator.=
..." would specify what happens when prefix "..." is applied =
to a value of that type. I don't see a need for a restriction here, sin=
ce I don't think there is any ambiguity between these two.</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>4.</div><div>Consider =
the following code:</div>
<div><br></div><blockquote style=3D"margin:0px 0px 0px 40px;border:none;pad=
ding:0px"><div><div><font face=3D"courier new, monospace">struct A { using =
Y =3D int; };</font></div></div></blockquote><blockquote style=3D"margin:0p=
x 0px 0px 40px;border:none;padding:0px">
<div><font face=3D"courier new, monospace">struct B { using Y =3D char; };<=
/font></div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;borde=
r:none;padding:0px"><div><div><font face=3D"courier new, monospace"><br></f=
ont></div>
<div><font face=3D"courier new, monospace">struct X {</font></div><div><fon=
t face=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </s=
pan>using ... =3D ...types<A, B>;</font></div><div><span style=3D"fon=
t-family:'courier new',monospace;white-space:pre-wrap"> </span><spa=
n style=3D"font-family:'courier new',monospace">struct Y {</span><b=
r>
</div><div><font face=3D"courier new, monospace"><span style=3D"white-space=
:pre-wrap"> </span></font><span style=3D"font-family:'courier new',=
monospace;white-space:pre-wrap"> </span><span style=3D"font-family:'cou=
rier new',monospace">using ... =3D ...types<float, double>;</span=
></div>
<div><span style=3D"font-family:'courier new',monospace;white-space=
:pre-wrap"> </span><span style=3D"font-family:'courier new',monospa=
ce">};</span><font face=3D"courier new, monospace"><br></font></div><div><f=
ont face=3D"courier new, monospace">};</font></div>
</div><div><font face=3D"courier new, monospace"><br></font></div><div><fon=
t face=3D"courier new, monospace">void f(...X::Y...);</font></div></blockqu=
ote><div><br></div><div>The definition of f looks ambiguous to me; it is no=
t clear if the ... prefix applies to X or Y. Is it equivalent to</div>
<blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div>=
<font face=3D"courier new, monospace">void f(int, char);</font></div></bloc=
kquote><div>or</div><blockquote style=3D"margin:0px 0px 0px 40px;border:non=
e;padding:0px">
<div><font face=3D"courier new, monospace">void f(float, double);</font></d=
iv></blockquote><div>?</div></div></blockquote><div><br></div><div>That'=
;s a great question. I was intending for it to mean the latter, but that ma=
kes it really hard to express the former. I think your approach of allowing=
member typedef packs solves this really nicely.</div>
</div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b6723d6dbd86404ed1fabc2--
.
Author: Alex B <devalexb@gmail.com>
Date: Tue, 10 Dec 2013 14:32:34 -0500
Raw View
--001a11c356249a831804ed332cc8
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
>
> The 'typename' would be required here, to indicate that the complete
> qualified-id names a type (pack). Consider:
>
> ...AType::static_tuple_data_member...
>
> I'd previously been expecting the syntax for the above to be:
>
> ...typename AType::data_types...
>
> for consistency with ... as a prefix operator on values, but you raise an
> excellent point (implied here and made explicit in your question 4): we
> could potentially want to turn any element of a nested name specifier int=
o
> a pack. That being the case, one possible way of writing this would be:
>
> typename AType::...data_types
>
> However, that introduces an ambiguity in the expression case. Is:
>
> ...AType::static_tuple_data_member...
>
Thinking about it, we could add support for parenthesises to disambiguate.
Parenthesises can be used when dealing with values, but not with types. We
could add also support for the following:
(... T)::U
which would apply packification on T (and not on T::U which would be the
default without parenthesises). So we could have:
1) (...A)::b
2) ...(A::b) // or simply:
...A::b
3) typename (...A)::B
4) typename ...(A::B) // error
typename ...A::B // ok
5) (...a).b
6) ...(a.b) // or simply:
...a.b
Note that I do not propose generalizing the use of optional parenthesises
when dealing with types (things could quickly become conflicting with
function declarations and function pointers). An opening parenthesis
followed by an ellipsis would have a very special meaning. The example in
4) is thus invalid.
constexpr auto seq =3D int_seq<0, 1, 2, 3, 4>();
> constexpr auto seq2 =3D int_seq<...seq * 2 ...>();
>
> ... or ...
>
> using seq =3D int_seq<0, 1, 2, 3, 4>;
> using seq2 =3D int_seq<...seq{} * 2 ...>;
>
> ... seem nearly-as-good syntaxes for the same thing.
>
It sounds fair enough to me.
Yes. "using ... =3D " would specify what happens when prefix ..." is applie=
d
> to the type, "operator..." would specify what happens when prefix "..." i=
s
> applied to a value of that type. I don't see a need for a restriction her=
e,
> since I don't think there is any ambiguity between these two.
>
I think there can be ambiguity. Consider a class A which defines both.
struct A {
using ... =3D ...types<int, long>;
using Ret =3D types<float, double>;
...Ret operator...() const { return (...Ret)1; }
};
f(...A{}...);
Are we calling
f(0, 0L);
or
f(1.0f, 1.0);
?
With my suggested parenthesises usage:
f(...A{}...); // =3D=3D> f(1.0f, 1.0);
f((...A){}...); // =3D=3D=AD> f(0, 0L);
>
>> 4.
>> Consider the following code:
>>
>> struct A { using Y =3D int; };
>>
>> struct B { using Y =3D char; };
>>
>>
>> struct X {
>> using ... =3D ...types<A, B>;
>> struct Y {
>> using ... =3D ...types<float, double>;
>> };
>> };
>>
>> void f(...X::Y...);
>>
>>
>> The definition of f looks ambiguous to me; it is not clear if the ...
>> prefix applies to X or Y. Is it equivalent to
>>
>> void f(int, char);
>>
>> or
>>
>> void f(float, double);
>>
>> ?
>>
>
> That's a great question. I was intending for it to mean the latter, but
> that makes it really hard to express the former.
>
One (very ugly) way to do it is:
void f(decltype(declval<...X>())::Y...);
Another (less ugly) way is:
template <class T>
using identity =3D T;
void f(identity<...X>::Y...);
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c356249a831804ed332cc8
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex">
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
><div>The 'typename' would be required here, to indicate that the c=
omplete qualified-id names a type (pack). Consider:<br></div></div><div><br=
>
</div>
<div>=A0 ...AType::static_tuple_data_member...</div><div><br></div><div>I&#=
39;d previously been expecting the syntax for the above to be:</div>
<div><br></div><div>=A0 ...typename AType::data_types...</div><div><br></di=
v><div>for consistency with ... as a prefix operator on values, but you rai=
se an excellent point (implied here and made explicit in your question 4): =
we could potentially want to turn any element of a nested name specifier in=
to a pack. That being the case, one possible way of writing this would be:<=
/div>
<div><br></div><div>=A0 typename AType::...data_types</div><div><br></div><=
div>However, that introduces an ambiguity in the expression case. Is:</div>=
<div><br></div><div>=A0 ...AType::static_tuple_data_member...</div></div></=
div>
</div></blockquote><div><br></div><div>Thinking about it, we could add supp=
ort for parenthesises to disambiguate. Parenthesises can be used when deali=
ng with values, but not with types. We could add also support for the follo=
wing:<br>
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote">
<div>=A0 =A0 <font face=3D"courier new, monospace">(... T)::U</font></div><=
div>which would apply packification on T (and not on T::U which would be th=
e default without parenthesises). So we could have:</div><div><blockquote s=
tyle=3D"margin:0px 0px 0px 40px;border:none;padding:0px">
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><font face=3D"courier=
new, monospace">1) (...A)::b</font></div></div><div class=3D"gmail_extra">=
<div class=3D"gmail_quote"><font face=3D"courier new, monospace">2) ...(A::=
b) =A0// or simply:</font></div>
</div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;border:none=
;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><font f=
ace=3D"courier new, monospace">=A0 =A0...A::b</font></div></div></blockquot=
e><blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px">
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><font face=3D"courier=
new, monospace">3) typename (...A)::B</font></div></div><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><font face=3D"courier new, monospace">4=
) typename ...(A::B) =A0// error</font></div>
</div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;border:none=
;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><font f=
ace=3D"courier new, monospace">=A0 =A0typename ...A::B =A0 =A0// ok</font><=
/div></div>
</blockquote>
<blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><font face=3D"courier new,=
monospace">5) (...a).b</font></div></div><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote">
<font face=3D"courier new, monospace">6) ...(a.b) =A0// or simply:</font></=
div></div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;border:=
none;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><fo=
nt face=3D"courier new, monospace">=A0 =A0...a.b</font></div>
</div></blockquote></div><div><br></div><div>Note that I do not propose gen=
eralizing the use of optional parenthesises when dealing with types (things=
could quickly become conflicting with function declarations and function p=
ointers). An opening parenthesis followed by an ellipsis would have a very =
special meaning. The example in 4) is thus invalid.</div>
<div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra">
<div class=3D"gmail_quote"><div>=A0 constexpr auto seq =3D int_seq<0, 1,=
2, 3, 4>();</div><div>=A0 constexpr auto seq2 =3D int_seq<...seq * 2=
...>();</div><div><br></div><div>... or ...</div><div><div><br></div><d=
iv>=A0 using seq =3D int_seq<0, 1, 2, 3, 4>;</div>
<div>=A0 using seq2 =3D int_seq<...seq{} * 2 ...>;</div><div><br></di=
v></div><div>... seem nearly-as-good syntaxes for the same thing.</div></di=
v></div></div></blockquote><div><br></div><div>It sounds fair enough to me.=
</div>
<div>=A0</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra">
<div class=3D"gmail_quote"><div>Yes. "using ... =3D " would speci=
fy what happens when prefix ..." is applied to the type, "operato=
r..." would specify what happens when prefix "..." is applie=
d to a value of that type. I don't see a need for a restriction here, s=
ince I don't think there is any ambiguity between these two.</div>
</div></div></div></blockquote><div><br></div><div>I think there can be amb=
iguity. Consider a class A which defines both.<br></div><div><br></div></di=
v></div><blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0p=
x">
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"co=
urier new, monospace">struct A {</font></div></div></div><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div><font face=3D"courier new, monospa=
ce">=A0 =A0 using ... =3D ...types<int, long>;</font></div>
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"courier new, monospace">=A0 =A0=A0</font></div></div></div><div c=
lass=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"courier =
new, monospace">=A0 =A0 using Ret =3D types<float, double>;</font></d=
iv>
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"courier new, monospace">=A0 =A0 ...Ret operator...() const { retu=
rn (...Ret)1; }</font></div></div></div><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote">
<div><font face=3D"courier new, monospace">};</font></div></div></div><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"courier=
new, monospace"><br></font></div></div></div><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote">
<div><font face=3D"courier new, monospace">f(...A{}...);</font></div></div>=
</div></blockquote><div class=3D"gmail_extra"><div class=3D"gmail_quote"><d=
iv><br></div><div>Are we calling</div></div></div><blockquote style=3D"marg=
in:0px 0px 0px 40px;border:none;padding:0px">
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"co=
urier new, monospace">f(0, 0L);</font></div></div></div></blockquote><div c=
lass=3D"gmail_extra"><div class=3D"gmail_quote"><div>or</div></div></div><b=
lockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px">
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"co=
urier new, monospace">f(1.0f, 1.0);</font></div></div></div></blockquote><d=
iv class=3D"gmail_extra"><div class=3D"gmail_quote"><div>?</div><div><br></=
div><div>
With my suggested parenthesises usage:</div><div><br></div></div></div><blo=
ckquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"g=
mail_extra"><div class=3D"gmail_quote"><div><font face=3D"courier new, mono=
space">f(...A{}...); =A0 // =3D=3D> f(1.0f, 1.0);</font></div>
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"courier new, monospace">f((...A){}...); // =3D=3D=AD> f(0, 0L)=
;</font></div></div></div></blockquote><div class=3D"gmail_extra"><div clas=
s=3D"gmail_quote">
<div><br></div><div>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div=
class=3D"gmail_quote">
<div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>4.</div><div>Consider =
the following code:</div>
<div><br></div><blockquote style=3D"margin:0px 0px 0px 40px;border:none;pad=
ding:0px"><div><div><font face=3D"courier new, monospace">struct A { using =
Y =3D int; };</font></div></div></blockquote><blockquote style=3D"margin:0p=
x 0px 0px 40px;border:none;padding:0px">
<div><font face=3D"courier new, monospace">struct B { using Y =3D char; };<=
/font></div></blockquote><blockquote style=3D"margin:0px 0px 0px 40px;borde=
r:none;padding:0px"><div><div><font face=3D"courier new, monospace"><br></f=
ont></div>
<div><font face=3D"courier new, monospace">struct X {</font></div><div><fon=
t face=3D"courier new, monospace"><span style=3D"white-space:pre-wrap"> </s=
pan>using ... =3D ...types<A, B>;</font></div><div><span style=3D"fon=
t-family:'courier new',monospace;white-space:pre-wrap"> </span><spa=
n style=3D"font-family:'courier new',monospace">struct Y {</span><b=
r>
</div><div><font face=3D"courier new, monospace"><span style=3D"white-space=
:pre-wrap"> </span></font><span style=3D"font-family:'courier new',=
monospace;white-space:pre-wrap"> </span><span style=3D"font-family:'cou=
rier new',monospace">using ... =3D ...types<float, double>;</span=
></div>
<div><span style=3D"font-family:'courier new',monospace;white-space=
:pre-wrap"> </span><span style=3D"font-family:'courier new',monospa=
ce">};</span><font face=3D"courier new, monospace"><br></font></div><div><f=
ont face=3D"courier new, monospace">};</font></div>
</div><div><font face=3D"courier new, monospace"><br></font></div><div><fon=
t face=3D"courier new, monospace">void f(...X::Y...);</font></div></blockqu=
ote><div><br></div><div>The definition of f looks ambiguous to me; it is no=
t clear if the ... prefix applies to X or Y. Is it equivalent to</div>
<blockquote style=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div>=
<font face=3D"courier new, monospace">void f(int, char);</font></div></bloc=
kquote><div>or</div><blockquote style=3D"margin:0px 0px 0px 40px;border:non=
e;padding:0px">
<div><font face=3D"courier new, monospace">void f(float, double);</font></d=
iv></blockquote><div>?</div></div></blockquote><div><br></div></div><div>Th=
at's a great question. I was intending for it to mean the latter, but t=
hat makes it really hard to express the former.</div>
</div></div></div></blockquote><div><br></div><div><div>One (very ugly) way=
to do it is:</div><div><br></div></div></div></div><blockquote style=3D"ma=
rgin:0px 0px 0px 40px;border:none;padding:0px"><div class=3D"gmail_extra">
<div class=3D"gmail_quote">
<div><div><font face=3D"courier new, monospace">void f(decltype(declval<=
....X>())::Y...);</font></div></div></div></div></blockquote><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div>=A0</div><div>Another (les=
s ugly) way is:</div>
<div><br></div></div></div><blockquote style=3D"margin:0 0 0 40px;border:no=
ne;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>=
<font face=3D"courier new, monospace">template <class T></font></div>=
</div>
</div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=
=3D"courier new, monospace">using identity =3D T;</font></div></div></div><=
div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"cou=
rier new, monospace"><br>
</font></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quo=
te"><div><font face=3D"courier new, monospace">void f(identity<...X>:=
:Y...);</font></div></div></div></blockquote><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote">
<div>=A0</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote">
</div></div></div>
<p></p>
-- <br />
<br />
--- <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c356249a831804ed332cc8--
.