Topic: Pack expansion: blocks, switch/case


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 5 Jul 2016 06:28:08 -0700 (PDT)
Raw View
------=_Part_230_1656601912.1467725288509
Content-Type: multipart/alternative;
 boundary="----=_Part_231_1214881347.1467725288510"

------=_Part_231_1214881347.1467725288510
Content-Type: text/plain; charset=UTF-8

Hello together,

during development of my "Compile-time trie"-based string matcher
<https://github.com/smilingthax/cttrie>, I wanted to use the compiler's
advanced code generation for switch statements (instead of non-optimized
recursion/unrolling), but had to use preprocessor based techniques
(cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of an
appropriate pack-expansion.
And because the set of generated case-values is *mostly* sparse, using a
table-based technique (i.e. generate an array of function pointers via pack
expansion) was also not adequate.
A short web search also brought up some
<http://stackoverflow.com/questions/32235855/switch-statement-variadic-template-expansion>
StackOverflow
<http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates>
questions
<http://stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variadic-templates>
asking for switch/case with parameter packs.

A first syntax idea was:

  template <typename... Transitions> auto Switch(TrieNode<Transitions...>
....) {
    // ...
    switch (ch) {
      case 0: ... special code ... break;

      case (Transitions::Char) {  // Note: no ":"   // the label has to be
constexpr (nothing new)
        return checkTrie(Transitions::Next(),str,...); }...

    }
    // return error;
  }

But while reviewing some possible/desired features:

   - allow mix of pack-expanded and regular case statements inside a single
   switch
   - break / continue / [[fallthrough]]  should work as usual   (this rules
   out lambda-based approaches)
   - goto into the case body can't work (duplicate label)
   - default label only possible the "old way", not via pack expansion.
   - introduces Block scope??  (-> variable lifetime...)

I found the a more* general* solution: A *pack-expansion for Blocks*, e.g.

template <int... Is> void function(...)
{
  // ...some normal code

  {
    f(Is);
    // more block code, probably using Is - or other packs of same length
  }...

  // ...some more normal code
}

which simplifies code where, up until now, techniques like
// helper to execute('map') parameter pack:  pass({(f(args),0)...});
inline void pass(const std::initializer_list<int> &) {}
had to be used.

Example with switch/case:

template <typename... Transitions> auto Switch(TrieNode<Transitions...> ...)
  // ...
  switch (ch) {
    { case Transitions::Char:
      return checkTrie(Transitions::Next(),...); }...
  }
 // ...

This requires almost no changes to the C++ syntax, because a switch-block
is not very different from other blocks (even permitting constructs like
Duff's device).

  Tobias

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c61bd22c-d7c8-4f14-a65f-1a5b7100fa22%40isocpp.org.

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

<div dir=3D"ltr">Hello together,=C2=A0<br><br>during development of my=C2=
=A0<a href=3D"https://github.com/smilingthax/cttrie">&quot;Compile-time tri=
e&quot;-based string matcher</a>, I wanted to use the compiler&#39;s advanc=
ed code generation for switch statements (instead of non-optimized recursio=
n/unrolling), but had to use preprocessor based techniques (cttrie_sw256-bo=
ost.tcc, cttrie_sw32-boost.tcc), due to the lack of an appropriate pack-exp=
ansion.<br>And because the set of generated case-values is <i>mostly</i> sp=
arse, using a table-based technique (i.e. generate an array of function poi=
nters via pack expansion) was also not adequate.<div>A short web search als=
o brought up <a href=3D"http://stackoverflow.com/questions/32235855/switch-=
statement-variadic-template-expansion">some</a> <a href=3D"http://stackover=
flow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates">S=
tackOverflow</a> <a href=3D"http://stackoverflow.com/questions/18757271/how=
-to-build-switch-case-with-variadic-templates">questions</a> asking for swi=
tch/case with parameter packs.<br><div><br><div><div>A first syntax idea wa=
s:</div><div><br></div><div class=3D"prettyprint" style=3D"border: 1px soli=
d rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250=
, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;</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"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Transitions</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Switch</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">TrieNode</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Transitions</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">...&gt;</span><span style=3D"colo=
r: #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: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled=
-by-prettify">// ...</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">switch</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ch</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</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"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">case</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> special code </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: #008;" class=3D"styled-by-prettify">break</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> <br><br>=C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ca=
se</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Transitions</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Char</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</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-p=
rettify"> =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// Note: no &quot;:&quot; =C2=A0 // the label has to be constexpr (no=
thing new)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> checkTrie</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Transitions</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Next</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><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"co=
lor: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// return error;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></=
code></div><div><div><br><div><div>But while reviewing some possible/desire=
d features:</div><div><ul><li>allow mix of pack-expanded and regular case s=
tatements inside a single switch<br></li><li>break / continue / [[fallthrou=
gh]] =C2=A0should work as usual =C2=A0 (this rules out lambda-based approac=
hes)<br></li><li>goto into the case body can&#39;t work (duplicate label)<b=
r></li><li>default label only possible the &quot;old way&quot;, not via pac=
k expansion.<br></li><li>introduces Block scope?? =C2=A0(-&gt; variable lif=
etime...)<br></li></ul></div><div>I found the a more<i> general</i> solutio=
n: A <b>pack-expansion for Blocks</b>, e.g.<br></div></div><div><br></div><=
div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); wo=
rd-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Is</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">function</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(...)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prett=
ify">// ...some normal code</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0<br>=C2=A0 </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 f</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Is</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// more block code, probably using Is - or other p=
acks of same length</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}...</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">// ...some more normal code</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span></div></code></div><div><br></div><div>which simplifi=
es code where, up until now, techniques like<br></div><div class=3D"prettyp=
rint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word;=
 background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// helper to execute(&#39;map&#39;) parameter pack: =C2=A0pass({(f(ar=
gs),0)...});</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">inli=
ne</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">pass</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" c=
lass=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"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">initializer_list</span><span style=3D"color: #080;" class=3D"styl=
ed-by-prettify">&lt;int&gt;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&amp;)</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></=
div></code></div><div>had to be used.<br></div><div><br></div><div>Example =
with switch/case:</div></div><div><br></div><div><div class=3D"prettyprint"=
 style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; back=
ground-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">template</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</sp=
an><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"styled-by-prettify"> </span><span style=3D"=
color: #606;" class=3D"styled-by-prettify">Transitions</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Switch</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">TrieNode</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Transi=
tions</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">...)</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span=
 style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">switch</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">ch</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">case</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Transitions</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">Char</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> checkTrie</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Transitions</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Next</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(),...);</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0<=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">// ...</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></di=
v></code></div><br>This requires almost no changes to the C++ syntax, becau=
se a switch-block is not very different from other blocks (even permitting =
constructs like Duff&#39;s device).<br><br>=C2=A0 Tobias<br><br></div></div=
></div></div></div></div>

<p></p>

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

------=_Part_231_1214881347.1467725288510--

------=_Part_230_1656601912.1467725288509--

.


Author: inkwizytoryankes@gmail.com
Date: Tue, 5 Jul 2016 06:43:26 -0700 (PDT)
Raw View
------=_Part_107_2108920738.1467726206287
Content-Type: multipart/alternative;
 boundary="----=_Part_108_126517283.1467726206288"

------=_Part_108_126517283.1467726206288
Content-Type: text/plain; charset=UTF-8



On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, smili...@googlemail.com wrote:
>
> Hello together,
>
> during development of my "Compile-time trie"-based string matcher
> <https://github.com/smilingthax/cttrie>, I wanted to use the compiler's
> advanced code generation for switch statements (instead of non-optimized
> recursion/unrolling), but had to use preprocessor based techniques
> (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of an
> appropriate pack-expansion.
> And because the set of generated case-values is *mostly* sparse, using a
> table-based technique (i.e. generate an array of function pointers via pack
> expansion) was also not adequate.
> A short web search also brought up some
> <http://stackoverflow.com/questions/32235855/switch-statement-variadic-template-expansion>
> StackOverflow
> <http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates>
> questions
> <http://stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variadic-templates>
> asking for switch/case with parameter packs.
>
> A first syntax idea was:
>
>   template <typename... Transitions> auto Switch(TrieNode<Transitions...>
> ...) {
>     // ...
>     switch (ch) {
>       case 0: ... special code ... break;
>
>       case (Transitions::Char) {  // Note: no ":"   // the label has to
> be constexpr (nothing new)
>         return checkTrie(Transitions::Next(),str,...); }...
>
>     }
>     // return error;
>   }
>
> But while reviewing some possible/desired features:
>
>    - allow mix of pack-expanded and regular case statements inside a
>    single switch
>    - break / continue / [[fallthrough]]  should work as usual   (this
>    rules out lambda-based approaches)
>    - goto into the case body can't work (duplicate label)
>    - default label only possible the "old way", not via pack expansion.
>    - introduces Block scope??  (-> variable lifetime...)
>
> I found the a more* general* solution: A *pack-expansion for Blocks*, e.g.
>
> template <int... Is> void function(...)
> {
>   // ...some normal code
>
>   {
>     f(Is);
>     // more block code, probably using Is - or other packs of same length
>   }...
>
>   // ...some more normal code
> }
>
> which simplifies code where, up until now, techniques like
> // helper to execute('map') parameter pack:  pass({(f(args),0)...});
> inline void pass(const std::initializer_list<int> &) {}
> had to be used.
>
> Example with switch/case:
>
> template <typename... Transitions> auto Switch(TrieNode<Transitions...>
> ...)
>   // ...
>   switch (ch) {
>     { case Transitions::Char:
>       return checkTrie(Transitions::Next(),...); }...
>   }
>  // ...
>
> This requires almost no changes to the C++ syntax, because a switch-block
> is not very different from other blocks (even permitting constructs like
> Duff's device).
>
>   Tobias
>

Similar proposition  float around there couple of times.
One example:
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J
More general cases:
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/14ddd53c-8ec8-4e73-8f41-ebd8e33c2073%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, smil=
i...@googlemail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
 dir=3D"ltr">Hello together,=C2=A0<br><br>during development of my=C2=A0<a =
href=3D"https://github.com/smilingthax/cttrie" target=3D"_blank" rel=3D"nof=
ollow" onmousedown=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttp=
s%3A%2F%2Fgithub.com%2Fsmilingthax%2Fcttrie\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEgNw85OtmgTO9SFwWCPgIPVrovrg&#39;;return true;" onclick=3D"this.hr=
ef=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fsmilin=
gthax%2Fcttrie\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9SFwWCPg=
IPVrovrg&#39;;return true;">&quot;Compile-time trie&quot;-based string matc=
her</a>, I wanted to use the compiler&#39;s advanced code generation for sw=
itch statements (instead of non-optimized recursion/unrolling), but had to =
use preprocessor based techniques (cttrie_sw256-boost.tcc, cttrie_sw32-boos=
t.tcc), due to the lack of an appropriate pack-expansion.<br>And because th=
e set of generated case-values is <i>mostly</i> sparse, using a table-based=
 technique (i.e. generate an array of function pointers via pack expansion)=
 was also not adequate.<div>A short web search also brought up <a href=3D"h=
ttp://stackoverflow.com/questions/32235855/switch-statement-variadic-templa=
te-expansion" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fque=
stions%2F32235855%2Fswitch-statement-variadic-template-expansion\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true=
;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2F=
stackoverflow.com%2Fquestions%2F32235855%2Fswitch-statement-variadic-templa=
te-expansion\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvO=
jH0gwA&#39;;return true;">some</a> <a href=3D"http://stackoverflow.com/ques=
tions/7381805/c-c11-switch-statement-for-variadic-templates" target=3D"_bla=
nk" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;http://www.google.com/=
url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F7381805%2Fc-c11-switc=
h-statement-for-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
FSnz3KJnPepmegLhvuvP_JkXceCA&#39;;return true;" onclick=3D"this.href=3D&#39=
;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%=
2F7381805%2Fc-c11-switch-statement-for-variadic-templates\x26sa\x3dD\x26snt=
z\x3d1\x26usg\x3dAFQjCNFSnz3KJnPepmegLhvuvP_JkXceCA&#39;;return true;">Stac=
kOverflow</a> <a href=3D"http://stackoverflow.com/questions/18757271/how-to=
-build-switch-case-with-variadic-templates" target=3D"_blank" rel=3D"nofoll=
ow" onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%=
2F%2Fstackoverflow.com%2Fquestions%2F18757271%2Fhow-to-build-switch-case-wi=
th-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzfYhdWZD=
afcPGPLeMTaybxA&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.g=
oogle.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F18757271%2F=
how-to-build-switch-case-with-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x2=
6usg\x3dAFQjCNHzyeFzfYhdWZDafcPGPLeMTaybxA&#39;;return true;">questions</a>=
 asking for switch/case with parameter packs.<br><div><br><div><div>A first=
 syntax idea was:</div><div><br></div><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:#000">=C2=A0 </span><span style=3D"color:#008">temp=
late</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#008">typename</span><span style=3D"color:#66=
0">...</span><span style=3D"color:#000"> </span><span style=3D"color:#606">=
Transitions</span><span style=3D"color:#660">&gt;</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">auto</span><span style=3D"color:=
#000"> </span><span style=3D"color:#606">Switch</span><span style=3D"color:=
#660">(</span><span style=3D"color:#606">TrieNode</span><span style=3D"colo=
r:#660">&lt;</span><span style=3D"color:#606">Transitions</span><span style=
=3D"color:#660">...<wbr>&gt;</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">...)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </=
span><span style=3D"color:#800">// ...</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">switch</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">ch</span><span style=3D"color:#660">)</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span st=
yle=3D"color:#660">:</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">...</span><span style=3D"color:#000"> special code </span><=
span style=3D"color:#660">...</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#008">break</span><span style=3D"color:#660">;</span><span=
 style=3D"color:#000"> <br><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">case</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">(</span><span style=3D"color:#606">Transitions</span><span style=
=3D"color:#660">::</span><span style=3D"color:#606">Char</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"> =C2=A0</span><span style=3D"=
color:#800">// Note: no &quot;:&quot; =C2=A0 // the label has to be constex=
pr (nothing new)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> checkTrie</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#606">Transitions</span><span style=3D"color:#660">::</span><span style=
=3D"color:#606">Next</span><span style=3D"color:#660">(),</span><span style=
=3D"color:#000"><wbr>str</span><span style=3D"color:#660">,...);</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">}...</span><span =
style=3D"color:#000"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color:#800">// return error;</span><span style=3D"color:#000"><br>=C2=
=A0 </span><span style=3D"color:#660">}</span></div></code></div><div><div>=
<br><div><div>But while reviewing some possible/desired features:</div><div=
><ul><li>allow mix of pack-expanded and regular case statements inside a si=
ngle switch<br></li><li>break / continue / [[fallthrough]] =C2=A0should wor=
k as usual =C2=A0 (this rules out lambda-based approaches)<br></li><li>goto=
 into the case body can&#39;t work (duplicate label)<br></li><li>default la=
bel only possible the &quot;old way&quot;, not via pack expansion.<br></li>=
<li>introduces Block scope?? =C2=A0(-&gt; variable lifetime...)<br></li></u=
l></div><div>I found the a more<i> general</i> solution: A <b>pack-expansio=
n for Blocks</b>, e.g.<br></div></div><div><br></div><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:#008">template</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#008">int</span><span style=3D"color:#660">...</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#606">Is</span><span style=3D"color:#=
660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#00=
8">void</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>function</span><span style=3D"color:#660">(...)</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 </span><span style=3D"color:#800">// ...some normal code</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0<br>=C2=A0 </span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 f</span><span style=3D"color:#660">(</span><span style=3D"color:#606">I=
s</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#800">// more block code, probabl=
y using Is - or other packs of same length</span><span style=3D"color:#000"=
><br>=C2=A0 </span><span style=3D"color:#660">}...</span><span style=3D"col=
or:#000"><br><br>=C2=A0 </span><span style=3D"color:#800">// ...some more n=
ormal code</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">}</span><span style=3D"color:#000"><br></span></div></code></div><di=
v><br></div><div>which simplifies code where, up until now, techniques like=
<br></div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-w=
ord;background-color:rgb(250,250,250)"><code><div><span style=3D"color:#800=
">// helper to execute(&#39;map&#39;) parameter pack: =C2=A0pass({(f(args),=
0)...});</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
008">inline</span><span style=3D"color:#000"> </span><span style=3D"color:#=
008">void</span><span style=3D"color:#000"> </span><span style=3D"color:#00=
8">pass</span><span style=3D"color:#660">(</span><span style=3D"color:#008"=
>const</span><span style=3D"color:#000"> std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">initializer_list</span><span style=
=3D"color:#080">&lt;int&gt;</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">&amp;)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">{}</span><span style=3D"color:#000"><br></span></div><=
/code></div><div>had to be used.<br></div><div><br></div><div>Example with =
switch/case:</div></div><div><br></div><div><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:#008">template</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008"=
>typename</span><span style=3D"color:#660">...</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Transitions</span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">auto</span><span style=3D"color:#000"> </span><span style=3D"color:=
#606">Switch</span><span style=3D"color:#660">(</span><span style=3D"color:=
#606">TrieNode</span><span style=3D"color:#660">&lt;</span><span style=3D"c=
olor:#606">Transitions</span><span style=3D"color:#660">...<wbr>&gt;</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">...)</span><s=
pan style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">// ..=
..</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#=
008">switch</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">ch</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#606"=
>Transitions</span><span style=3D"color:#660">::</span><span style=3D"color=
:#606">Char</span><span style=3D"color:#660">:</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</spa=
n><span style=3D"color:#000"> checkTrie</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#606">Transitions</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#606">Next</span><span style=3D"color:#660=
">(),<wbr>...);</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">}...</span><span style=3D"color:#000"><br>=C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0</span><span =
style=3D"color:#800">// ...</span><span style=3D"color:#000"><br></span></d=
iv></code></div><br>This requires almost no changes to the C++ syntax, beca=
use a switch-block is not very different from other blocks (even permitting=
 constructs like Duff&#39;s device).<br><br>=C2=A0 Tobias<br></div></div></=
div></div></div></div></blockquote><div>=C2=A0</div><div>Similar propositio=
n=C2=A0 float around there couple of times.<br>One example:<br>https://grou=
ps.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/=
std-proposals/LoDJDCDDyH8/L3TUatFwm98J<br>More general cases:<br>https://gr=
oups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/pack=
s/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ<br>https://groups.google.com/a/iso=
cpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/zym3j=
2iJyZg/su9ERhh28GwJ<br>https://groups.google.com/a/isocpp.org/forum/?fromgr=
oups#!topic/std-proposals/2hdpLnXJKkQ<br><br><br><br></div></div>

<p></p>

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

------=_Part_108_126517283.1467726206288--

------=_Part_107_2108920738.1467726206287--

.


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 5 Jul 2016 10:02:57 -0700 (PDT)
Raw View
------=_Part_436_725122754.1467738177655
Content-Type: multipart/alternative;
 boundary="----=_Part_437_1259207071.1467738177662"

------=_Part_437_1259207071.1467738177662
Content-Type: text/plain; charset=UTF-8

On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, inkwizyt...@gmail.com wrote:
>
> On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, smili...@googlemail.com
> wrote:
>>
>> Hello together,
>>
>> during development of my "Compile-time trie"-based string matcher
>> <https://github.com/smilingthax/cttrie>, I wanted to use the compiler's
>> advanced code generation for switch statements (instead of non-optimized
>> recursion/unrolling), but had to use preprocessor based techniques
>> (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of an
>> appropriate pack-expansion.
>> And because the set of generated case-values is *mostly* sparse, using a
>> table-based technique (i.e. generate an array of function pointers via pack
>> expansion) was also not adequate.
>> A short web search also brought up some
>> <http://stackoverflow.com/questions/32235855/switch-statement-variadic-template-expansion>
>> StackOverflow
>> <http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates>
>> questions
>> <http://stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variadic-templates>
>> asking for switch/case with parameter packs.
>>
>> A first syntax idea was:
>>
>>   template <typename... Transitions> auto Switch(TrieNode<Transitions...>
>> ...) {
>>     // ...
>>     switch (ch) {
>>       case 0: ... special code ... break;
>>
>>       case (Transitions::Char) {  // Note: no ":"   // the label has to
>> be constexpr (nothing new)
>>         return checkTrie(Transitions::Next(),str,...); }...
>>
>>     }
>>     // return error;
>>   }
>>
>> But while reviewing some possible/desired features:
>>
>>    - allow mix of pack-expanded and regular case statements inside a
>>    single switch
>>    - break / continue / [[fallthrough]]  should work as usual   (this
>>    rules out lambda-based approaches)
>>    - goto into the case body can't work (duplicate label)
>>    - default label only possible the "old way", not via pack expansion.
>>    - introduces Block scope??  (-> variable lifetime...)
>>
>> I found the a more* general* solution: A *pack-expansion for Blocks*,
>> e.g.
>>
>> template <int... Is> void function(...)
>> {
>>   // ...some normal code
>>
>>   {
>>     f(Is);
>>     // more block code, probably using Is - or other packs of same length
>>   }...
>>
>>   // ...some more normal code
>> }
>>
>> which simplifies code where, up until now, techniques like
>> // helper to execute('map') parameter pack:  pass({(f(args),0)...});
>> inline void pass(const std::initializer_list<int> &) {}
>> had to be used.
>>
>> Example with switch/case:
>>
>> template <typename... Transitions> auto Switch(TrieNode<Transitions...>
>> ...)
>>   // ...
>>   switch (ch) {
>>     { case Transitions::Char:
>>       return checkTrie(Transitions::Next(),...); }...
>>   }
>>  // ...
>>
>> This requires almost no changes to the C++ syntax, because a switch-block
>> is not very different from other blocks (even permitting constructs like
>> Duff's device).
>>
>>   Tobias
>>
>
> Similar proposition  float around there couple of times.
> One example:
>
> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J
> More general cases:
>
> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ
>
> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ
>
> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
>

I'm well aware of existing expression-expansion ideas - but these
(probably) won't help with the switch statement.
Even more, if we have block/statement-expansion, you can easily use it in
an expression context by wrapping it in an immediately executed lambda.

But what I don't quite understand: Given the general interest in such a
feature (for which you gave some more examples), why do all these proposals
seem to go nowhere?

Adding Block/Statement expansion seem quite easy - both the implementation
and the specification. At least, I haven't heard of any substantial issues
in those areas.

I'm not talking about anything fancy, just
  {
    // statements as in a normal block
  }...
with the explicit allowance for use in conjunction with switch/case (and
I've given some the design considerations in my initial mail).

Why not bake such simple basics into the language and consider all the
other ideas only as a second step?

At least, I'd be helpful to have SOME guidance from the standardization
body, whether they prefer such a simple solution or whether they'd like
more work done on "for constexpr"(e.g.).
And, if block/statement expansion won't move forward (for now), maybe add a
more specific expansion for switch/case (something akin to the "first
syntax idea" from my first mail)?

  Tobias

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/648eb3c5-488c-4b1b-8be2-02a0ac454220%40isocpp.org.

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

<div dir=3D"ltr">On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, inkwizyt...@=
gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, <a>smili...@googlemail.com=
</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:=
0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Hello t=
ogether,=C2=A0<br><br>during development of my=C2=A0<a href=3D"https://gith=
ub.com/smilingthax/cttrie" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.c=
om%2Fsmilingthax%2Fcttrie\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85Otm=
gTO9SFwWCPgIPVrovrg&#39;;return true;" onclick=3D"this.href=3D&#39;https://=
www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fsmilingthax%2Fcttrie\x26=
sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9SFwWCPgIPVrovrg&#39;;retu=
rn true;">&quot;Compile-time trie&quot;-based string matcher</a>, I wanted =
to use the compiler&#39;s advanced code generation for switch statements (i=
nstead of non-optimized recursion/unrolling), but had to use preprocessor b=
ased techniques (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the=
 lack of an appropriate pack-expansion.<br>And because the set of generated=
 case-values is <i>mostly</i> sparse, using a table-based technique (i.e. g=
enerate an array of function pointers via pack expansion) was also not adeq=
uate.<div>A short web search also brought up <a href=3D"http://stackoverflo=
w.com/questions/32235855/switch-statement-variadic-template-expansion" rel=
=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D&#39;http://www.=
google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F32235855%2=
Fswitch-statement-variadic-template-expansion\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true;" onclick=3D"this.=
href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2=
Fquestions%2F32235855%2Fswitch-statement-variadic-template-expansion\x26sa\=
x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return =
true;">some</a> <a href=3D"http://stackoverflow.com/questions/7381805/c-c11=
-switch-statement-for-variadic-templates" rel=3D"nofollow" target=3D"_blank=
" onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F=
%2Fstackoverflow.com%2Fquestions%2F7381805%2Fc-c11-switch-statement-for-var=
iadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFSnz3KJnPepmegLhvuv=
P_JkXceCA&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F7381805%2Fc-c11-s=
witch-statement-for-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAF=
QjCNFSnz3KJnPepmegLhvuvP_JkXceCA&#39;;return true;">StackOverflow</a> <a hr=
ef=3D"http://stackoverflow.com/questions/18757271/how-to-build-switch-case-=
with-variadic-templates" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"=
this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.=
com%2Fquestions%2F18757271%2Fhow-to-build-switch-case-with-variadic-templat=
es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzfYhdWZDafcPGPLeMTaybxA&#39=
;;return true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3d=
http%3A%2F%2Fstackoverflow.com%2Fquestions%2F18757271%2Fhow-to-build-switch=
-case-with-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeF=
zfYhdWZDafcPGPLeMTaybxA&#39;;return true;">questions</a> asking for switch/=
case with parameter packs.<br><div><br><div><div>A first syntax idea was:</=
div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);word-wra=
p:break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"c=
olor:#000">=C2=A0 </span><span style=3D"color:#008">template</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">&lt;</span><span styl=
e=3D"color:#008">typename</span><span style=3D"color:#660">...</span><span =
style=3D"color:#000"> </span><span style=3D"color:#606">Transitions</span><=
span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">auto</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#606">Switch</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#606">TrieNode</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#606">Transitions</span><span style=3D"color:#660">...=
<wbr>&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">...)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D=
"color:#800">// ...</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">switch</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">ch</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">...</s=
pan><span style=3D"color:#000"> special code </span><span style=3D"color:#6=
60">...</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>break</span><span style=3D"color:#660">;</span><span style=3D"color:#000">=
 <br><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span=
 style=3D"color:#606">Transitions</span><span style=3D"color:#660">::</span=
><span style=3D"color:#606">Char</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"> =C2=A0</span><span style=3D"color:#800">// Note: no &=
quot;:&quot; =C2=A0 // the label has to be constexpr (nothing new)</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> checkTrie</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#606">Transitions</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#606">Next</spa=
n><span style=3D"color:#660">(),</span><span style=3D"color:#000"><wbr>str<=
/span><span style=3D"color:#660">,...);</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">}...</span><span style=3D"color:#000"><br>=
<br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#800">// return e=
rror;</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"col=
or:#660">}</span></div></code></div><div><div><br><div><div>But while revie=
wing some possible/desired features:</div><div><ul><li>allow mix of pack-ex=
panded and regular case statements inside a single switch<br></li><li>break=
 / continue / [[fallthrough]] =C2=A0should work as usual =C2=A0 (this rules=
 out lambda-based approaches)<br></li><li>goto into the case body can&#39;t=
 work (duplicate label)<br></li><li>default label only possible the &quot;o=
ld way&quot;, not via pack expansion.<br></li><li>introduces Block scope?? =
=C2=A0(-&gt; variable lifetime...)<br></li></ul></div><div>I found the a mo=
re<i> general</i> solution: A <b>pack-expansion for Blocks</b>, e.g.<br></d=
iv></div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);wor=
d-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">&lt;</span><span style=3D"color:#008">int</span><span sty=
le=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Is</span><span style=3D"color:#660">&gt;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">void</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">function</span><span sty=
le=3D"color:#660">(...)</span><span style=3D"color:#000"><br></span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><s=
pan style=3D"color:#800">// ...some normal code</span><span style=3D"color:=
#000"><br>=C2=A0 =C2=A0 =C2=A0<br>=C2=A0 </span><span style=3D"color:#660">=
{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 f</span><span style=3D=
"color:#660">(</span><span style=3D"color:#606">Is</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span=
 style=3D"color:#800">// more block code, probably using Is - or other pack=
s of same length</span><span style=3D"color:#000"><br>=C2=A0 </span><span s=
tyle=3D"color:#660">}...</span><span style=3D"color:#000"><br><br>=C2=A0 </=
span><span style=3D"color:#800">// ...some more normal code</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span></div></code></div><div><br></div><div>which sim=
plifies code where, up until now, techniques like<br></div><div style=3D"bo=
rder:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(2=
50,250,250)"><code><div><span style=3D"color:#800">// helper to execute(&#3=
9;map&#39;) parameter pack: =C2=A0pass({(f(args),0)...});</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">inline</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">void</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">pass</span><span style=
=3D"color:#660">(</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">initializer_list</span><span style=3D"color:#080">&lt;int&g=
t;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&amp=
;)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</=
span><span style=3D"color:#000"><br></span></div></code></div><div>had to b=
e used.<br></div><div><br></div><div>Example with switch/case:</div></div><=
div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);word-wra=
p:break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"c=
olor:#008">template</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">&lt;</span><span style=3D"color:#008">typename</span><span sty=
le=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Transitions</span><span style=3D"color:#660">&gt;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">auto</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#606">Switch</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#606">TrieNode</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#606">Transitions</=
span><span style=3D"color:#660">...<wbr>&gt;</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">...)</span><span style=3D"color:#000"=
><br>=C2=A0 </span><span style=3D"color:#800">// ...</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#008">switch</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">ch</span><span style=3D"color:#660">)</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">case</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#606">Transitions</span><span=
 style=3D"color:#660">::</span><span style=3D"color:#606">Char</span><span =
style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> checkTrie</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#606">Transitions</span><span style=3D"color:#660">::</span><span style=
=3D"color:#606">Next</span><span style=3D"color:#660">(),<wbr>...);</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">}...</span><sp=
an style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#800">//=
 ...</span><span style=3D"color:#000"><br></span></div></code></div><br>Thi=
s requires almost no changes to the C++ syntax, because a switch-block is n=
ot very different from other blocks (even permitting constructs like Duff&#=
39;s device).<br><br>=C2=A0 Tobias<br></div></div></div></div></div></div><=
/blockquote><div>=C2=A0</div><div>Similar proposition=C2=A0 float around th=
ere couple of times.<br>One example:<br><a href=3D"https://groups.google.co=
m/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposal=
s/LoDJDCDDyH8/L3TUatFwm98J" target=3D"_blank" rel=3D"nofollow" onmousedown=
=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgrou=
ps#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J&#39=
;;return true;" onclick=3D"this.href=3D&#39;https://groups.google.com/a/iso=
cpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJD=
CDDyH8/L3TUatFwm98J&#39;;return true;">https://groups.google.com/a/<wbr>iso=
cpp.org/forum/?fromgroups#!<wbr>searchin/std-proposals/packs/<wbr>std-propo=
sals/LoDJDCDDyH8/<wbr>L3TUatFwm98J</a><br>More general cases:<br><a href=3D=
"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-pro=
posals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ" target=3D"_blank" rel=
=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://groups.google.com/a/i=
socpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHd=
wZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;" onclick=3D"this.href=3D&#39;https:=
//groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/=
packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;">https://gro=
ups.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-propo=
sals/packs/<wbr>std-proposals/GHdwZbYY8L0/Jqf_<wbr>yfvyHAAJ</a><br><a href=
=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-=
proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ" target=3D"_blank" r=
el=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://groups.google.com/a=
/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/z=
ym3j2iJyZg/su9ERhh28GwJ&#39;;return true;" onclick=3D"this.href=3D&#39;http=
s://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposal=
s/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ&#39;;return true;">https://g=
roups.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-pro=
posals/packs/<wbr>std-proposals/zym3j2iJyZg/<wbr>su9ERhh28GwJ</a><br><a hre=
f=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-pr=
oposals/2hdpLnXJKkQ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this=
..href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topi=
c/std-proposals/2hdpLnXJKkQ&#39;;return true;" onclick=3D"this.href=3D&#39;=
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposa=
ls/2hdpLnXJKkQ&#39;;return true;">https://groups.google.com/a/<wbr>isocpp.o=
rg/forum/?fromgroups#!<wbr>topic/std-proposals/<wbr>2hdpLnXJKkQ</a></div></=
div></blockquote><div><br></div><div>I&#39;m well aware of existing express=
ion-expansion ideas - but these (probably) won&#39;t help with the switch s=
tatement.</div><div>Even more, if we have block/statement-expansion, you ca=
n easily use it in an expression context by wrapping it in an immediately e=
xecuted lambda.</div><div><br></div><div>But what I don&#39;t quite underst=
and: Given the general interest in such a feature (for which you gave some =
more examples), why do all these proposals seem to go nowhere?</div><div><b=
r></div><div>Adding Block/Statement expansion seem quite easy - both the im=
plementation and the specification. At least, I haven&#39;t heard of any su=
bstantial issues in those areas.</div><div><br></div><div>I&#39;m not talki=
ng about anything fancy, just</div><div class=3D"prettyprint" style=3D"bord=
er: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: =
rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettypri=
nt"><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> <br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">// statements as=
 in a normal block</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}...</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div><div>with the explicit allowance for use i=
n conjunction with switch/case (and I&#39;ve given some the design consider=
ations in my initial mail).<br></div><div><br></div><div>Why not bake such =
simple basics into the language and consider all the other ideas only as a =
second step?</div><div><br></div><div>At least, I&#39;d be helpful to have =
SOME guidance from the standardization body, whether they prefer such a sim=
ple solution or whether they&#39;d like more work done on &quot;for constex=
pr&quot;(e.g.).=C2=A0<br>And, if=C2=A0block/statement expansion won&#39;t m=
ove forward (for now), maybe=C2=A0add a more specific expansion for switch/=
case (something akin to the &quot;first syntax idea&quot; from my first mai=
l)?</div><div><br></div><div>=C2=A0 Tobias</div><div><br></div></div>

<p></p>

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

------=_Part_437_1259207071.1467738177662--

------=_Part_436_725122754.1467738177655--

.


Author: inkwizytoryankes@gmail.com
Date: Tue, 5 Jul 2016 12:07:51 -0700 (PDT)
Raw View
------=_Part_816_1851826799.1467745671919
Content-Type: multipart/alternative;
 boundary="----=_Part_817_623284867.1467745671920"

------=_Part_817_623284867.1467745671920
Content-Type: text/plain; charset=UTF-8



On Tuesday, July 5, 2016 at 7:02:58 PM UTC+2, smili...@googlemail.com wrote:
>
> On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, inkwizyt...@gmail.com wrote:
>>
>> On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, smili...@googlemail.com
>> wrote:
>>>
>>> Hello together,
>>>
>>> during development of my "Compile-time trie"-based string matcher
>>> <https://github.com/smilingthax/cttrie>, I wanted to use the compiler's
>>> advanced code generation for switch statements (instead of non-optimized
>>> recursion/unrolling), but had to use preprocessor based techniques
>>> (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of an
>>> appropriate pack-expansion.
>>> And because the set of generated case-values is *mostly* sparse, using
>>> a table-based technique (i.e. generate an array of function pointers via
>>> pack expansion) was also not adequate.
>>> A short web search also brought up some
>>> <http://stackoverflow.com/questions/32235855/switch-statement-variadic-template-expansion>
>>> StackOverflow
>>> <http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates>
>>> questions
>>> <http://stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variadic-templates>
>>> asking for switch/case with parameter packs.
>>>
>> [...]
>>> This requires almost no changes to the C++ syntax, because a
>>> switch-block is not very different from other blocks (even permitting
>>> constructs like Duff's device).
>>>
>>>   Tobias
>>>
>>
>> Similar proposition  float around there couple of times.
>> One example:
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J
>> More general cases:
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
>>
>
> I'm well aware of existing expression-expansion ideas - but these
> (probably) won't help with the switch statement.
> Even more, if we have block/statement-expansion, you can easily use it in
> an expression context by wrapping it in an immediately executed lambda.
>
> But what I don't quite understand: Given the general interest in such a
> feature (for which you gave some more examples), why do all these proposals
> seem to go nowhere?
>
>
Probably biggest reason is that nobody did needed legworking to push it
further.

Primary reason why I post it to prevent repeating same discussion. You can
try find new arguments but
most of feedback that you would get is probably same as in that links (this
is not full list I only grab couple of last one that I remember).


> Adding Block/Statement expansion seem quite easy - both the implementation
> and the specification. At least, I haven't heard of any substantial issues
> in those areas.
>
> I'm not talking about anything fancy, just
>   {
>     // statements as in a normal block
>   }...
> with the explicit allowance for use in conjunction with switch/case (and
> I've given some the design considerations in my initial mail).
>
> Why not bake such simple basics into the language and consider all the
> other ideas only as a second step?
>
> At least, I'd be helpful to have SOME guidance from the standardization
> body, whether they prefer such a simple solution or whether they'd like
> more work done on "for constexpr"(e.g.).
> And, if block/statement expansion won't move forward (for now), maybe add
> a more specific expansion for switch/case (something akin to the "first
> syntax idea" from my first mail)?
>
>   Tobias
>
>
Is hard for me to answer that because I only user of this public list, but
probably best way would be add all alternative version in one paper with
all pros/cons and ask for vote on committee meeting what version is most
preferred.
I would personally prefer `for constexpr` because with small tweaks it
would allow usage outside templates.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c614d89e-9533-42f2-a8aa-d8a1f762a00f%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Tuesday, July 5, 2016 at 7:02:58 PM UTC+2, smil=
i...@googlemail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
 dir=3D"ltr">On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, <a>inkwizyt...@g=
mail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
>On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, <a>smili...@googlemail.com</=
a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Hello tog=
ether,=C2=A0<br><br>during development of my=C2=A0<a href=3D"https://github=
..com/smilingthax/cttrie" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"=
this.href=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2=
Fsmilingthax%2Fcttrie\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9=
SFwWCPgIPVrovrg&#39;;return true;" onclick=3D"this.href=3D&#39;https://www.=
google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fsmilingthax%2Fcttrie\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9SFwWCPgIPVrovrg&#39;;return t=
rue;">&quot;Compile-time trie&quot;-based string matcher</a>, I wanted to u=
se the compiler&#39;s advanced code generation for switch statements (inste=
ad of non-optimized recursion/unrolling), but had to use preprocessor based=
 techniques (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lac=
k of an appropriate pack-expansion.<br>And because the set of generated cas=
e-values is <i>mostly</i> sparse, using a table-based technique (i.e. gener=
ate an array of function pointers via pack expansion) was also not adequate=
..<div>A short web search also brought up <a href=3D"http://stackoverflow.co=
m/questions/32235855/switch-statement-variadic-template-expansion" rel=3D"n=
ofollow" target=3D"_blank" onmousedown=3D"this.href=3D&#39;http://www.googl=
e.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F32235855%2Fswit=
ch-statement-variadic-template-expansion\x26sa\x3dD\x26sntz\x3d1\x26usg\x3d=
AFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true;" onclick=3D"this.href=
=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fque=
stions%2F32235855%2Fswitch-statement-variadic-template-expansion\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true=
;">some</a> <a href=3D"http://stackoverflow.com/questions/7381805/c-c11-swi=
tch-statement-for-variadic-templates" rel=3D"nofollow" target=3D"_blank" on=
mousedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fs=
tackoverflow.com%2Fquestions%2F7381805%2Fc-c11-switch-statement-for-variadi=
c-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFSnz3KJnPepmegLhvuvP_Jk=
XceCA&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.com/=
url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F7381805%2Fc-c11-switc=
h-statement-for-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
FSnz3KJnPepmegLhvuvP_JkXceCA&#39;;return true;">StackOverflow</a> <a href=
=3D"http://stackoverflow.com/questions/18757271/how-to-build-switch-case-wi=
th-variadic-templates" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"th=
is.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.co=
m%2Fquestions%2F18757271%2Fhow-to-build-switch-case-with-variadic-templates=
\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzfYhdWZDafcPGPLeMTaybxA&#39;;=
return true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dht=
tp%3A%2F%2Fstackoverflow.com%2Fquestions%2F18757271%2Fhow-to-build-switch-c=
ase-with-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzf=
YhdWZDafcPGPLeMTaybxA&#39;;return true;">questions</a> asking for switch/ca=
se with parameter packs. <br></div></div></blockquote></div></blockquote></=
div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><div><div>[...]<br><div><div><di=
v>This requires almost no changes to the C++ syntax, because a switch-block=
 is not very different from other blocks (even permitting constructs like D=
uff&#39;s device).<br><br>=C2=A0 Tobias<br></div></div></div></div></div></=
div></blockquote><div>=C2=A0</div><div>Similar proposition=C2=A0 float arou=
nd there couple of times.<br>One example:<br><a href=3D"https://groups.goog=
le.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-pro=
posals/LoDJDCDDyH8/L3TUatFwm98J" rel=3D"nofollow" target=3D"_blank" onmouse=
down=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?from=
groups#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J=
&#39;;return true;" onclick=3D"this.href=3D&#39;https://groups.google.com/a=
/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/L=
oDJDCDDyH8/L3TUatFwm98J&#39;;return true;">https://groups.google.com/a/<wbr=
>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-proposals/packs/<wbr>std-p=
roposals/LoDJDCDDyH8/<wbr>L3TUatFwm98J</a><br>More general cases:<br><a hre=
f=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std=
-proposals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D&#39;https://groups.google.com/=
a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/=
GHdwZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;" onclick=3D"this.href=3D&#39;htt=
ps://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposa=
ls/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;">https://=
groups.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-pr=
oposals/packs/<wbr>std-proposals/GHdwZbYY8L0/Jqf_<wbr>yfvyHAAJ</a><br><a hr=
ef=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/st=
d-proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ" rel=3D"nofollow" =
target=3D"_blank" onmousedown=3D"this.href=3D&#39;https://groups.google.com=
/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals=
/zym3j2iJyZg/su9ERhh28GwJ&#39;;return true;" onclick=3D"this.href=3D&#39;ht=
tps://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-propos=
als/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ&#39;;return true;">https:/=
/groups.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-p=
roposals/packs/<wbr>std-proposals/zym3j2iJyZg/<wbr>su9ERhh28GwJ</a><br><a h=
ref=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-=
proposals/2hdpLnXJKkQ" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"th=
is.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!to=
pic/std-proposals/2hdpLnXJKkQ&#39;;return true;" onclick=3D"this.href=3D&#3=
9;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-propo=
sals/2hdpLnXJKkQ&#39;;return true;">https://groups.google.com/a/<wbr>isocpp=
..org/forum/?fromgroups#!<wbr>topic/std-proposals/<wbr>2hdpLnXJKkQ</a></div>=
</div></blockquote><div><br></div><div>I&#39;m well aware of existing expre=
ssion-expansion ideas - but these (probably) won&#39;t help with the switch=
 statement.</div><div>Even more, if we have block/statement-expansion, you =
can easily use it in an expression context by wrapping it in an immediately=
 executed lambda.</div><div><br></div><div>But what I don&#39;t quite under=
stand: Given the general interest in such a feature (for which you gave som=
e more examples), why do all these proposals seem to go nowhere?</div><div>=
<br></div></div></blockquote><div><br>Probably biggest reason is that nobod=
y did needed legworking to push it further.<br><br>Primary reason why I pos=
t it to prevent repeating same discussion. You can try find new arguments b=
ut<br>most of feedback that you would get is probably same as in that links=
 (this is not full list I only grab couple of last one that I remember). <b=
r>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div></div><div>Adding Block/Statement expansion seem quite easy - both th=
e implementation and the specification. At least, I haven&#39;t heard of an=
y substantial issues in those areas.</div><div><br></div><div>I&#39;m not t=
alking about anything fancy, just</div><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:#000">=C2=A0 </span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"> <br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#800">// statements as in a normal block</span><span style=3D"color:#00=
0"><br>=C2=A0 </span><span style=3D"color:#660">}...</span><span style=3D"c=
olor:#000"><br></span></div></code></div><div>with the explicit allowance f=
or use in conjunction with switch/case (and I&#39;ve given some the design =
considerations in my initial mail).<br></div><div><br></div><div>Why not ba=
ke such simple basics into the language and consider all the other ideas on=
ly as a second step?</div><div><br></div><div>At least, I&#39;d be helpful =
to have SOME guidance from the standardization body, whether they prefer su=
ch a simple solution or whether they&#39;d like more work done on &quot;for=
 constexpr&quot;(e.g.).=C2=A0<br>And, if=C2=A0block/statement expansion won=
&#39;t move forward (for now), maybe=C2=A0add a more specific expansion for=
 switch/case (something akin to the &quot;first syntax idea&quot; from my f=
irst mail)?</div><div><br></div><div>=C2=A0 Tobias</div><div><br></div></di=
v></blockquote><div><br>Is hard for me to answer that because I only user o=
f this public list, but probably best way would be add all alternative vers=
ion in one paper with all pros/cons and ask for vote on committee meeting w=
hat version is most preferred.<br>I would personally prefer `for constexpr`=
 because with small tweaks it would allow usage outside templates.<br></div=
></div>

<p></p>

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

------=_Part_817_623284867.1467745671920--

------=_Part_816_1851826799.1467745671919--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 5 Jul 2016 18:25:21 -0700 (PDT)
Raw View
------=_Part_5040_2103277047.1467768321964
Content-Type: multipart/alternative;
 boundary="----=_Part_5041_440441546.1467768321965"

------=_Part_5041_440441546.1467768321965
Content-Type: text/plain; charset=UTF-8

On Tuesday, July 5, 2016 at 1:02:58 PM UTC-4, smili...@googlemail.com wrote:
>
> On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, inkwizyt...@gmail.com wrote:
>>
>> On Tuesday, July 5, 2016 at 3:28:08 PM UTC+2, smili...@googlemail.com
>> wrote:
>>>
>>> Hello together,
>>>
>>> during development of my "Compile-time trie"-based string matcher
>>> <https://github.com/smilingthax/cttrie>, I wanted to use the compiler's
>>> advanced code generation for switch statements (instead of non-optimized
>>> recursion/unrolling), but had to use preprocessor based techniques
>>> (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of an
>>> appropriate pack-expansion.
>>> And because the set of generated case-values is *mostly* sparse, using
>>> a table-based technique (i.e. generate an array of function pointers via
>>> pack expansion) was also not adequate.
>>> A short web search also brought up some
>>> <http://stackoverflow.com/questions/32235855/switch-statement-variadic-template-expansion>
>>> StackOverflow
>>> <http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates>
>>> questions
>>> <http://stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variadic-templates>
>>> asking for switch/case with parameter packs.
>>>
>>> A first syntax idea was:
>>>
>>>   template <typename... Transitions> auto Switch(TrieNode<Transitions
>>> ...> ...) {
>>>     // ...
>>>     switch (ch) {
>>>       case 0: ... special code ... break;
>>>
>>>       case (Transitions::Char) {  // Note: no ":"   // the label has to
>>> be constexpr (nothing new)
>>>         return checkTrie(Transitions::Next(),str,...); }...
>>>
>>>     }
>>>     // return error;
>>>   }
>>>
>>> But while reviewing some possible/desired features:
>>>
>>>    - allow mix of pack-expanded and regular case statements inside a
>>>    single switch
>>>    - break / continue / [[fallthrough]]  should work as usual   (this
>>>    rules out lambda-based approaches)
>>>    - goto into the case body can't work (duplicate label)
>>>    - default label only possible the "old way", not via pack expansion.
>>>    - introduces Block scope??  (-> variable lifetime...)
>>>
>>> I found the a more* general* solution: A *pack-expansion for Blocks*,
>>> e.g.
>>>
>>> template <int... Is> void function(...)
>>> {
>>>   // ...some normal code
>>>
>>>   {
>>>     f(Is);
>>>     // more block code, probably using Is - or other packs of same
>>> length
>>>   }...
>>>
>>>   // ...some more normal code
>>> }
>>>
>>> which simplifies code where, up until now, techniques like
>>> // helper to execute('map') parameter pack:  pass({(f(args),0)...});
>>> inline void pass(const std::initializer_list<int> &) {}
>>> had to be used.
>>>
>>> Example with switch/case:
>>>
>>> template <typename... Transitions> auto Switch(TrieNode<Transitions...>
>>> ...)
>>>   // ...
>>>   switch (ch) {
>>>     { case Transitions::Char:
>>>       return checkTrie(Transitions::Next(),...); }...
>>>   }
>>>  // ...
>>>
>>> This requires almost no changes to the C++ syntax, because a
>>> switch-block is not very different from other blocks (even permitting
>>> constructs like Duff's device).
>>>
>>>   Tobias
>>>
>>
>> Similar proposition  float around there couple of times.
>> One example:
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J
>> More general cases:
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ
>>
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
>>
>
> I'm well aware of existing expression-expansion ideas - but these
> (probably) won't help with the switch statement.
> Even more, if we have block/statement-expansion, you can easily use it in
> an expression context by wrapping it in an immediately executed lambda.
>
> But what I don't quite understand: Given the general interest in such a
> feature (for which you gave some more examples), why do all these proposals
> seem to go nowhere?
>

Things don't get standardized because someone posts a suggestion in a
mailing list. Things get standardized because someone puts work and effort
into it, pushing it forward at actual standards meetings.

This ML is useful for figuring out what a proposal ought to be. But you
can't treat it as a place where you drop off an idea and hope that someone
else does something with it. Well, you can, but if you do, you shouldn't be
surprised if your idea never goes anywhere.

Adding Block/Statement expansion seem quite easy - both the implementation
> and the specification. At least, I haven't heard of any substantial issues
> in those areas.
>

Then it shouldn't be difficult for you to *prove* that. After all, if it's
that easy to implement, you ought to be able to fork Clang or GCC and
implement it, right? If it's that easy to specify, then you should be able
to write the appropriate standards wording for it.

It's easy to say that *someone else's* job is easy. It's not so easy when
you have to do it yourself.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/06c62bfa-d7a5-45e4-89f0-375fc47c33b6%40isocpp.org.

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

<div dir=3D"ltr">On Tuesday, July 5, 2016 at 1:02:58 PM UTC-4, smili...@goo=
glemail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Tuesday, July 5, 2016 at 3:43:26 PM UTC+2, <a>inkwizyt...@gmail.com=
</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:=
0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Tues=
day, July 5, 2016 at 3:28:08 PM UTC+2, <a>smili...@googlemail.com</a> wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Hello together,=
=C2=A0<br><br>during development of my=C2=A0<a href=3D"https://github.com/s=
milingthax/cttrie" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.h=
ref=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fsmili=
ngthax%2Fcttrie\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9SFwWCP=
gIPVrovrg&#39;;return true;" onclick=3D"this.href=3D&#39;https://www.google=
..com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fsmilingthax%2Fcttrie\x26sa\x3dD\x2=
6sntz\x3d1\x26usg\x3dAFQjCNEgNw85OtmgTO9SFwWCPgIPVrovrg&#39;;return true;">=
&quot;Compile-time trie&quot;-based string matcher</a>, I wanted to use the=
 compiler&#39;s advanced code generation for switch statements (instead of =
non-optimized recursion/unrolling), but had to use preprocessor based techn=
iques (cttrie_sw256-boost.tcc, cttrie_sw32-boost.tcc), due to the lack of a=
n appropriate pack-expansion.<br>And because the set of generated case-valu=
es is <i>mostly</i> sparse, using a table-based technique (i.e. generate an=
 array of function pointers via pack expansion) was also not adequate.<div>=
A short web search also brought up <a href=3D"http://stackoverflow.com/ques=
tions/32235855/switch-statement-variadic-template-expansion" rel=3D"nofollo=
w" target=3D"_blank" onmousedown=3D"this.href=3D&#39;http://www.google.com/=
url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F32235855%2Fswitch-sta=
tement-variadic-template-expansion\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
HiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true;" onclick=3D"this.href=3D&#39=
;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%=
2F32235855%2Fswitch-statement-variadic-template-expansion\x26sa\x3dD\x26snt=
z\x3d1\x26usg\x3dAFQjCNHiD1Bs_KW8qKaa1dD2XnvOjH0gwA&#39;;return true;">some=
</a> <a href=3D"http://stackoverflow.com/questions/7381805/c-c11-switch-sta=
tement-for-variadic-templates" rel=3D"nofollow" target=3D"_blank" onmousedo=
wn=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackove=
rflow.com%2Fquestions%2F7381805%2Fc-c11-switch-statement-for-variadic-templ=
ates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFSnz3KJnPepmegLhvuvP_JkXceCA&#=
39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x=
3dhttp%3A%2F%2Fstackoverflow.com%2Fquestions%2F7381805%2Fc-c11-switch-state=
ment-for-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFSnz3KJ=
nPepmegLhvuvP_JkXceCA&#39;;return true;">StackOverflow</a> <a href=3D"http:=
//stackoverflow.com/questions/18757271/how-to-build-switch-case-with-variad=
ic-templates" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=
=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fstackoverflow.com%2Fque=
stions%2F18757271%2Fhow-to-build-switch-case-with-variadic-templates\x26sa\=
x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzfYhdWZDafcPGPLeMTaybxA&#39;;return =
true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2=
F%2Fstackoverflow.com%2Fquestions%2F18757271%2Fhow-to-build-switch-case-wit=
h-variadic-templates\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHzyeFzfYhdWZDa=
fcPGPLeMTaybxA&#39;;return true;">questions</a> asking for switch/case with=
 parameter packs.<br><div><br><div><div>A first syntax idea was:</div><div>=
<br></div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-w=
ord;background-color:rgb(250,250,250)"><code><div><span style=3D"color:#000=
">=C2=A0 </span><span style=3D"color:#008">template</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#008">typename</span><span style=3D"color:#660">...</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Transitions</span><span styl=
e=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Switch</span><span style=3D"color:#660">(</span><span style=
=3D"color:#606">TrieNode</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#606">Transitions</span><span style=3D"color:#660">...<wbr>&=
gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">...=
)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#800">// ...</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color:#008">switch</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">ch</span><span s=
tyle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">case</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#066">0</span><span style=3D"color:#660">:</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">...</span><s=
pan style=3D"color:#000"> special code </span><span style=3D"color:#660">..=
..</span><span style=3D"color:#000"> </span><span style=3D"color:#008">break=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> <br><=
br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=
=3D"color:#606">Transitions</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#606">Char</span><span style=3D"color:#660">)</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"> =C2=A0</span><span style=3D"color:#800">// Note: no &quot;=
:&quot; =C2=A0 // the label has to be constexpr (nothing new)</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">return</span><span style=3D"color:#000"> checkTrie</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#606">Transitions</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#606">Next</span><sp=
an style=3D"color:#660">(),</span><span style=3D"color:#000"><wbr>str</span=
><span style=3D"color:#660">,...);</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">}...</span><span style=3D"color:#000"><br><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#800">// return error=
;</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#=
660">}</span></div></code></div><div><div><br><div><div>But while reviewing=
 some possible/desired features:</div><div><ul><li>allow mix of pack-expand=
ed and regular case statements inside a single switch<br></li><li>break / c=
ontinue / [[fallthrough]] =C2=A0should work as usual =C2=A0 (this rules out=
 lambda-based approaches)<br></li><li>goto into the case body can&#39;t wor=
k (duplicate label)<br></li><li>default label only possible the &quot;old w=
ay&quot;, not via pack expansion.<br></li><li>introduces Block scope?? =C2=
=A0(-&gt; variable lifetime...)<br></li></ul></div><div>I found the a more<=
i> general</i> solution: A <b>pack-expansion for Blocks</b>, e.g.<br></div>=
</div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);word-w=
rap:break-word;background-color:rgb(250,250,250)"><code><div><span style=3D=
"color:#008">template</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#008">int</span><span style=
=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=3D=
"color:#606">Is</span><span style=3D"color:#660">&gt;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">void</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">function</span><span style=3D"=
color:#660">(...)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span =
style=3D"color:#800">// ...some normal code</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0<br>=C2=A0 </span><span style=3D"color:#660">{</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 f</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#606">Is</span><span style=3D"color:#=
660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#800">// more block code, probably using Is - or other packs of=
 same length</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=
=3D"color:#660">}...</span><span style=3D"color:#000"><br><br>=C2=A0 </span=
><span style=3D"color:#800">// ...some more normal code</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span></div></code></div><div><br></div><div>which sim=
plifies code where, up until now, techniques like<br></div><div style=3D"bo=
rder:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(2=
50,250,250)"><code><div><span style=3D"color:#800">// helper to execute(&#3=
9;map&#39;) parameter pack: =C2=A0pass({(f(args),0)...});</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">inline</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">void</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">pass</span><span style=
=3D"color:#660">(</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">initializer_list</span><span style=3D"color:#080">&lt;int&g=
t;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&amp=
;)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</=
span><span style=3D"color:#000"><br></span></div></code></div><div>had to b=
e used.<br></div><div><br></div><div>Example with switch/case:</div></div><=
div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);word-wra=
p:break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"c=
olor:#008">template</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">&lt;</span><span style=3D"color:#008">typename</span><span sty=
le=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Transitions</span><span style=3D"color:#660">&gt;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">auto</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#606">Switch</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#606">TrieNode</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#606">Transitions</=
span><span style=3D"color:#660">...<wbr>&gt;</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">...)</span><span style=3D"color:#000"=
><br>=C2=A0 </span><span style=3D"color:#800">// ...</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#008">switch</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">ch</span><span style=3D"color:#660">)</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">case</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#606">Transitions</span><span=
 style=3D"color:#660">::</span><span style=3D"color:#606">Char</span><span =
style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> checkTrie</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#606">Transitions</span><span style=3D"color:#660">::</span><span style=
=3D"color:#606">Next</span><span style=3D"color:#660">(),<wbr>...);</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">}...</span><sp=
an style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#800">//=
 ...</span><span style=3D"color:#000"><br></span></div></code></div><br>Thi=
s requires almost no changes to the C++ syntax, because a switch-block is n=
ot very different from other blocks (even permitting constructs like Duff&#=
39;s device).<br><br>=C2=A0 Tobias<br></div></div></div></div></div></div><=
/blockquote><div>=C2=A0</div><div>Similar proposition=C2=A0 float around th=
ere couple of times.<br>One example:<br><a href=3D"https://groups.google.co=
m/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposal=
s/LoDJDCDDyH8/L3TUatFwm98J" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgrou=
ps#!searchin/std-proposals/packs/std-proposals/LoDJDCDDyH8/L3TUatFwm98J&#39=
;;return true;" onclick=3D"this.href=3D&#39;https://groups.google.com/a/iso=
cpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/LoDJD=
CDDyH8/L3TUatFwm98J&#39;;return true;">https://groups.google.com/a/<wbr>iso=
cpp.org/forum/?fromgroups#!<wbr>searchin/std-proposals/packs/<wbr>std-propo=
sals/LoDJDCDDyH8/<wbr>L3TUatFwm98J</a><br>More general cases:<br><a href=3D=
"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-pro=
posals/packs/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ" rel=3D"nofollow" targe=
t=3D"_blank" onmousedown=3D"this.href=3D&#39;https://groups.google.com/a/is=
ocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/GHdw=
ZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;" onclick=3D"this.href=3D&#39;https:/=
/groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/p=
acks/std-proposals/GHdwZbYY8L0/Jqf_yfvyHAAJ&#39;;return true;">https://grou=
ps.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-propos=
als/packs/<wbr>std-proposals/GHdwZbYY8L0/Jqf_<wbr>yfvyHAAJ</a><br><a href=
=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-=
proposals/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ" rel=3D"nofollow" ta=
rget=3D"_blank" onmousedown=3D"this.href=3D&#39;https://groups.google.com/a=
/isocpp.org/forum/?fromgroups#!searchin/std-proposals/packs/std-proposals/z=
ym3j2iJyZg/su9ERhh28GwJ&#39;;return true;" onclick=3D"this.href=3D&#39;http=
s://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposal=
s/packs/std-proposals/zym3j2iJyZg/su9ERhh28GwJ&#39;;return true;">https://g=
roups.google.com/a/<wbr>isocpp.org/forum/?fromgroups#!<wbr>searchin/std-pro=
posals/packs/<wbr>std-proposals/zym3j2iJyZg/<wbr>su9ERhh28GwJ</a><br><a hre=
f=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-pr=
oposals/2hdpLnXJKkQ" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this=
..href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topi=
c/std-proposals/2hdpLnXJKkQ&#39;;return true;" onclick=3D"this.href=3D&#39;=
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposa=
ls/2hdpLnXJKkQ&#39;;return true;">https://groups.google.com/a/<wbr>isocpp.o=
rg/forum/?fromgroups#!<wbr>topic/std-proposals/<wbr>2hdpLnXJKkQ</a></div></=
div></blockquote><div><br></div><div>I&#39;m well aware of existing express=
ion-expansion ideas - but these (probably) won&#39;t help with the switch s=
tatement.</div><div>Even more, if we have block/statement-expansion, you ca=
n easily use it in an expression context by wrapping it in an immediately e=
xecuted lambda.</div><div><br></div><div>But what I don&#39;t quite underst=
and: Given the general interest in such a feature (for which you gave some =
more examples), why do all these proposals seem to go nowhere?</div></div><=
/blockquote><div><br>Things don&#39;t get standardized because someone post=
s a suggestion in a mailing list. Things get standardized because someone p=
uts work and effort into it, pushing it forward at actual standards meeting=
s.<br><br>This ML is useful for figuring out what a proposal ought to be. B=
ut you can&#39;t treat it as a place where you drop off an idea and hope th=
at someone else does something with it. Well, you can, but if you do, you s=
houldn&#39;t be surprised if your idea never goes anywhere.<br><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div=
>Adding Block/Statement expansion seem quite easy - both the implementation=
 and the specification. At least, I haven&#39;t heard of any substantial is=
sues in those areas.</div></div></blockquote><div><br>Then it shouldn&#39;t=
 be difficult for you to <i>prove</i> that. After all, if it&#39;s that eas=
y to implement, you ought to be able to fork Clang or GCC and implement it,=
 right? If it&#39;s that easy to specify, then you should be able to write =
the appropriate standards wording for it.<br><br>It&#39;s easy to say that =
<i>someone else&#39;s</i> job is easy. It&#39;s not so easy when you have t=
o do it yourself.<br></div></div>

<p></p>

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

------=_Part_5041_440441546.1467768321965--

------=_Part_5040_2103277047.1467768321964--

.


Author: Sergey Vidyuk <sir.vestnik@gmail.com>
Date: Wed, 6 Jul 2016 23:33:50 -0700 (PDT)
Raw View
------=_Part_6784_1381355976.1467873230344
Content-Type: multipart/alternative;
 boundary="----=_Part_6785_269634769.1467873230344"

------=_Part_6785_269634769.1467873230344
Content-Type: text/plain; charset=UTF-8


>
>
>> At least, I'd be helpful to have SOME guidance from the standardization
>> body, whether they prefer such a simple solution or whether they'd like
>> more work done on "for constexpr"(e.g.).
>>
> And, if block/statement expansion won't move forward (for now), maybe add
>> a more specific expansion for switch/case (something akin to the "first
>> syntax idea" from my first mail)?
>>
>
some info on for constexpr discussed here:
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
Right now I'm playing with gcc code (using my free time so progress is not
rapid enough). I want to have implementation I can play with and share with
other people on this list and then start to work on proposal paper.

I'm just maling list reader and have no relation to the standardization
body so I would like to know which design goal is better to solve
"statement folding" related tasks too.

Sergey

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8b6d75ab-6e5e-44ca-9ec6-c3c853ddbc38%40isocpp.org.

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

<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><br><div>At least, I&#39;d be h=
elpful to have SOME guidance from the standardization body, whether they pr=
efer such a simple solution or whether they&#39;d like more work done on &q=
uot;for constexpr&quot;(e.g.).=C2=A0<br></div></div></blockquote></div></bl=
ockquote><div></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And,=
 if=C2=A0block/statement expansion won&#39;t move forward (for now), maybe=
=C2=A0add a more specific expansion for switch/case (something akin to the =
&quot;first syntax idea&quot; from my first mail)?</div></div></blockquote>=
</div></blockquote><div><br>some info on for constexpr discussed here:=20
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposa=
ls/2hdpLnXJKkQ
 Right now I&#39;m playing with gcc code (using my free time so progress is=
=20
not rapid enough). I want to have implementation I can play with and=20
share=20
with other people on this list and then start to work on proposal paper.<br=
><br>I&#39;m just maling list reader and have no relation to the standardiz=
ation
 body so I would like to know which design goal is better to solve &quot;st=
atement folding&quot; related tasks too. <br></div><br>Sergey<br>

<p></p>

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

------=_Part_6785_269634769.1467873230344--

------=_Part_6784_1381355976.1467873230344--

.


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 7 Jul 2016 05:53:45 -0700 (PDT)
Raw View
------=_Part_4176_43500046.1467896025836
Content-Type: multipart/alternative;
 boundary="----=_Part_4177_2056080240.1467896025837"

------=_Part_4177_2056080240.1467896025837
Content-Type: text/plain; charset=UTF-8

On Wednesday, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bolas wrote:
>
> Things don't get standardized because someone posts a suggestion in a
> mailing list. Things get standardized because someone puts work and effort
> into it, pushing it forward at actual standards meetings.
>

Sure. But not all of us are in a position to participate in standards
meetings.


> This ML is useful for figuring out what a proposal ought to be. But you
> can't treat it as a place where you drop off an idea and hope that someone
> else does something with it. Well, you can, but if you do, you shouldn't be
> surprised if your idea never goes anywhere.
>

My actual point was that it's not just me, who would like to see such a
feature.


> Adding Block/Statement expansion seem quite easy - both the implementation
>> and the specification. At least, I haven't heard of any substantial issues
>> in those areas.
>>
>
> Then it shouldn't be difficult for you to *prove* that. After all, if
> it's that easy to implement, you ought to be able to fork Clang or GCC and
> implement it, right? If it's that easy to specify, then you should be able
> to write the appropriate standards wording for it.
>
> It's easy to say that *someone else's* job is easy. It's not so easy when
> you have to do it yourself.
>

Well, I've attached a first patch against clang HEAD with this grammar
change:

statement:
  // ...
  compound-statement
  compound-statement '...'   // <-- new
  // ....

It handles e.g.:

template <int... Is>
void bar()
{
  {
    printf("%d\n",Is);
  }...

  switch (1) {
    {
      case Is: printf("%d\n",Is);
    }...
  }
}
// ... bar<0,1,2>();

It will not handle nested structs and lamdas yet, e.g.:

template <int I> struct int_c {};

template <int I> struct MyType {
  typedef int_c<I> type;
};

template <int... Is> void foo()
{
  {
    struct X {
      static void bar(typename MyType<Is>::type mt) {
        // error: pack expansion does not contain any unexpanded parameter
packs
      }
    };
    // ...
  }...
}

and we probably want to disallow:

template <int... Is> void foo()
{
  {     // alternative: "([]{"
    struct X {
      static void bar() {
        printf("%d\n",Is);
      }
    }
  }...  // alternative: "return 0; }() || ...);"  // does not work either
}

because then unexpanded parameter packs would have to "escape" a function
body.
The first X::bar version does work, when the lambda+fold alternative is
used instead, so that's obviously more achievable.

  Tobias

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/edd84c67-f11a-4953-bfd0-e1e40f908dff%40isocpp.org.

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

<div dir=3D"ltr">On Wednesday, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
Things don&#39;t get standardized because someone posts a suggestion in a m=
ailing list. Things get standardized because someone puts work and effort i=
nto it, pushing it forward at actual standards meetings.<br></div></div></b=
lockquote><div><br></div><div>Sure. But not all of us are in a position to =
participate in standards meetings.</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>This ML is useful for fig=
uring out what a proposal ought to be. But you can&#39;t treat it as a plac=
e where you drop off an idea and hope that someone else does something with=
 it. Well, you can, but if you do, you shouldn&#39;t be surprised if your i=
dea never goes anywhere.<br></div></div></blockquote><div><div><br></div><d=
iv>My actual point was that it&#39;s not just me, who would like to see suc=
h a feature.</div></div><div>=C2=A0<br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div></div><div>Adding Block/Statement expansion seem quite e=
asy - both the implementation and the specification. At least, I haven&#39;=
t heard of any substantial issues in those areas.</div></div></blockquote><=
div><br>Then it shouldn&#39;t be difficult for you to <i>prove</i> that. Af=
ter all, if it&#39;s that easy to implement, you ought to be able to fork C=
lang or GCC and implement it, right? If it&#39;s that easy to specify, then=
 you should be able to write the appropriate standards wording for it.<br><=
br>It&#39;s easy to say that <i>someone else&#39;s</i> job is easy. It&#39;=
s not so easy when you have to do it yourself.<br></div></div></blockquote>=
<div><br></div><div>Well, I&#39;ve attached a first patch against clang HEA=
D with this grammar change:<br><br></div><div class=3D"prettyprint" style=
=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background=
-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">state=
ment</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 compoun=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">statement<br>=C2=
=A0 compound</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">-</span><span style=3D"color: #000;" class=3D"styled-by-prettify">stateme=
nt </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&#39;..=
..&#39;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=
=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// &lt=
;-- new</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
 ....</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span></div></code></div><div><br></div><div>It handles e.g.:<br><br></div>=
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); w=
ord-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">template</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Is</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> bar</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> <br>=C2=A0 =C2=A0 printf</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #080;" class=3D"styled-by-pre=
ttify">&quot;%d\n&quot;</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">,</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Is</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">}...</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">switch</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #066;" class=3D"styled-by-prettify">1</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"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">case</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prett=
ify">Is</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> printf</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #080;" class=3D"styled-by-prettify">&quot;%d\n&quot;</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">Is</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">}...</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> <br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// ... bar&lt;0,1,2&gt;();</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span></div></code></div><div><br></div><div>I=
t will not handle nested structs and lamdas yet, e.g.:<br><br><div class=3D=
"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: bre=
ak-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"=
><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled=
-by-prettify">template</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> I</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> int_c </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{};</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> I</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">MyType</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">typedef</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> int_c</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">I</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> type</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">template</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Is<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> X </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><font color=3D"#000000"><span style=3D"color: #000;" class=3D"styled-=
by-prettify">=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">static</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">MyType</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">Is</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&gt;::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">type mt</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></font><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><font color=3D"#000000"><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span></font><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// error: pack expansio=
n does not contain any unexpanded parameter packs</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">}...</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span></div></code></div><br>and=
 we probably want to disallow:<br><br><div class=3D"prettyprint" style=3D"b=
order: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-colo=
r: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subpretty=
print">template &lt;int... Is&gt; void foo()<br>{</div><div class=3D"subpre=
ttyprint"><font color=3D"#666600"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">=C2=A0 </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">// alternative: &quot;([]{&quot;</span></font><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><font color=3D"#0000=
00"><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 =C2=A0=
</span></font><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><font color=3D"#666600"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> X </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span></font><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">static</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 print=
f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;%d\n&quot;</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Is</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}... =C2=A0// alternative: =
&quot;return 0; }() || ...);&quot; =C2=A0// does not work either<br>}</span=
><font color=3D"#666600"></font></div></code></div><div><br>because then un=
expanded parameter packs would have to &quot;escape&quot; a function body.<=
br>The first X::bar version does work, when the lambda+fold alternative is =
used instead, so that&#39;s obviously more achievable.<br><br></div><div>=
=C2=A0 Tobias=C2=A0<br></div></div></div>

<p></p>

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

------=_Part_4177_2056080240.1467896025837--

------=_Part_4176_43500046.1467896025836
Content-Type: text/x-diff; charset=US-ASCII;
 name=clang_block_expansion-v0-r274740.patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename=clang_block_expansion-v0-r274740.patch
X-Attachment-Id: f4423882-04a1-4b01-80ca-a8abdf2e4549
Content-ID: <f4423882-04a1-4b01-80ca-a8abdf2e4549>

Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h (revision 274740)
+++ include/clang/AST/Expr.h (working copy)
@@ -108,7 +108,7 @@
 protected:
   Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
        bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
-    : Stmt(SC)
+    : Stmt(SC, ContainsUnexpandedParameterPack)
   {
     ExprBits.TypeDependent = TD;
     ExprBits.ValueDependent = VD;
@@ -115,12 +115,11 @@
     ExprBits.InstantiationDependent = ID;
     ExprBits.ValueKind = VK;
     ExprBits.ObjectKind = OK;
-    ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
     setType(T);
   }

   /// \brief Construct an empty expression.
-  explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+  explicit Expr(StmtClass SC, EmptyShell E) : Stmt(SC, E) { }

 public:
   QualType getType() const { return TR; }
@@ -195,30 +194,6 @@
     ExprBits.InstantiationDependent = ID;
   }

-  /// \brief Whether this expression contains an unexpanded parameter
-  /// pack (for C++11 variadic templates).
-  ///
-  /// Given the following function template:
-  ///
-  /// \code
-  /// template<typename F, typename ...Types>
-  /// void forward(const F &f, Types &&...args) {
-  ///   f(static_cast<Types&&>(args)...);
-  /// }
-  /// \endcode
-  ///
-  /// The expressions \c args and \c static_cast<Types&&>(args) both
-  /// contain parameter packs.
-  bool containsUnexpandedParameterPack() const {
-    return ExprBits.ContainsUnexpandedParameterPack;
-  }
-
-  /// \brief Set the bit that describes whether this expression
-  /// contains an unexpanded parameter pack.
-  void setContainsUnexpandedParameterPack(bool PP = true) {
-    ExprBits.ContainsUnexpandedParameterPack = PP;
-  }
-
   /// getExprLoc - Return the preferred location for the arrow when diagnosing
   /// a problem with a generic expression.
   SourceLocation getExprLoc() const LLVM_READONLY;
@@ -3800,8 +3775,8 @@
       ExprBits.TypeDependent |= expr->isTypeDependent();
       ExprBits.ValueDependent |= expr->isValueDependent();
       ExprBits.InstantiationDependent |= expr->isInstantiationDependent();
-      ExprBits.ContainsUnexpandedParameterPack |=
-          expr->containsUnexpandedParameterPack();
+      setContainsUnexpandedParameterPack(containsUnexpandedParameterPack() |
+                                       expr->containsUnexpandedParameterPack());
     }
   }

Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h (revision 274740)
+++ include/clang/AST/RecursiveASTVisitor.h (working copy)
@@ -2009,6 +2009,7 @@
     return true;
   }
 })
+DEF_TRAVERSE_STMT(PackExpansionStmt, {})
 DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
   TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
   TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h (revision 274740)
+++ include/clang/AST/Stmt.h (working copy)
@@ -80,11 +80,13 @@

   class StmtBitfields {
     friend class Stmt;
+    friend class ASTStmtReader; // deserialization

     /// \brief The statement class.
     unsigned sClass : 8;
+    unsigned ContainsUnexpandedParameterPack : 1;
   };
-  enum { NumStmtBits = 8 };
+  enum { NumStmtBits = 9 };

   class CompoundStmtBitfields {
     friend class CompoundStmt;
@@ -130,7 +132,6 @@
     unsigned TypeDependent : 1;
     unsigned ValueDependent : 1;
     unsigned InstantiationDependent : 1;
-    unsigned ContainsUnexpandedParameterPack : 1;
   };
   enum { NumExprBits = 16 };

@@ -336,13 +337,16 @@

 protected:
   /// \brief Construct an empty statement.
-  explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {}
+  explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC, false) {
+  }

 public:
-  Stmt(StmtClass SC) {
+  Stmt(StmtClass SC, bool ContainsUnexpandedParameterPack) {
     static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
                   "Insufficient alignment!");
     StmtBits.sClass = SC;
+    StmtBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+// printf("ctor %s %p %d\n",getStmtClassName(),(void*)this,ContainsUnexpandedParameterPack);
     if (StatisticsEnabled) Stmt::addStmtClass(SC);
   }

@@ -351,6 +355,31 @@
   }
   const char *getStmtClassName() const;

+  /// \brief Whether this statment/expression contains an unexpanded
+  /// parameter pack (for C++11 variadic templates).
+  ///
+  /// Given the following function template:
+  ///
+  /// \code
+  /// template<typename F, typename ...Types>
+  /// void forward(const F &f, Types &&...args) {
+  ///   f(static_cast<Types&&>(args)...);
+  /// }
+  /// \endcode
+  ///
+  /// The expressions \c args and \c static_cast<Types&&>(args) both
+  /// contain parameter packs.
+  bool containsUnexpandedParameterPack() const {
+    return StmtBits.ContainsUnexpandedParameterPack;
+  }
+
+  /// \brief Set the bit that describes whether this expression
+  /// contains an unexpanded parameter pack.
+  void setContainsUnexpandedParameterPack(bool PP = true) {
+// printf("set %s %p %d\n",getStmtClassName(),(void*)this,PP);
+    StmtBits.ContainsUnexpandedParameterPack = PP;
+  }
+
   /// SourceLocation tokens are not useful in isolation - they are low level
   /// value objects created/interpreted by SourceManager. We assume AST
   /// clients will have a pointer to the respective SourceManager.
@@ -446,8 +475,7 @@

 public:
   DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
-           SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
-                                    StartLoc(startLoc), EndLoc(endLoc) {}
+           SourceLocation endLoc);

   /// \brief Build an empty declaration statement.
   explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
@@ -519,7 +547,7 @@
   bool HasLeadingEmptyMacro;
 public:
   NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
-    : Stmt(NullStmtClass), SemiLoc(L),
+    : Stmt(NullStmtClass, false), SemiLoc(L),
       HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}

   /// \brief Build an empty null statement.
@@ -560,7 +588,8 @@

   // \brief Build an empty compound statement with a location.
   explicit CompoundStmt(SourceLocation Loc)
-    : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) {
+    : Stmt(CompoundStmtClass, false), Body(nullptr), LBraceLoc(Loc),
+      RBraceLoc(Loc) {
     CompoundStmtBits.NumStmts = 0;
   }

@@ -586,6 +615,8 @@

   void setLastStmt(Stmt *S) {
     assert(!body_empty() && "setLastStmt");
+    if (S->containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack(true);
     Body[size()-1] = S;
   }

@@ -653,12 +684,14 @@
   SourceLocation KeywordLoc;
   SourceLocation ColonLoc;

-  SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
-    : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {
+  SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc,
+             bool ContainsUnexpandedParameterPack)
+    : Stmt(SC, ContainsUnexpandedParameterPack), NextSwitchCase(nullptr),
+      KeywordLoc(KWLoc), ColonLoc(ColonLoc) {
   }

-  SwitchCase(StmtClass SC, EmptyShell)
-    : Stmt(SC), NextSwitchCase(nullptr) {}
+  SwitchCase(StmtClass SC, EmptyShell E)
+    : Stmt(SC, E), NextSwitchCase(nullptr) {}

 public:
   const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
@@ -691,14 +724,22 @@
   enum { LHS, RHS, SUBSTMT, END_EXPR };
   Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for
                              // GNU "case 1 ... 4" extension
+
+  void updateContainsUnexpandedParameterPack() {
+    setContainsUnexpandedParameterPack(
+      (SubExprs[SUBSTMT] && SubExprs[SUBSTMT]->containsUnexpandedParameterPack()) ||
+      SubExprs[LHS]->containsUnexpandedParameterPack() ||
+      (SubExprs[RHS] && SubExprs[RHS]->containsUnexpandedParameterPack()));
+  }
 public:
   CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
            SourceLocation ellipsisLoc, SourceLocation colonLoc)
-    : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
+    : SwitchCase(CaseStmtClass, caseLoc, colonLoc, false) {
     SubExprs[SUBSTMT] = nullptr;
     SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
     SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
     EllipsisLoc = ellipsisLoc;
+    updateContainsUnexpandedParameterPack();
   }

   /// \brief Build an empty switch case statement.
@@ -723,9 +764,18 @@
   }
   const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }

-  void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
-  void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
-  void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+  void setSubStmt(Stmt *S) {
+    SubExprs[SUBSTMT] = S;
+    updateContainsUnexpandedParameterPack();
+  }
+  void setLHS(Expr *Val) {
+    SubExprs[LHS] = reinterpret_cast<Stmt*>(Val);
+    updateContainsUnexpandedParameterPack();
+  }
+  void setRHS(Expr *Val) {
+    SubExprs[RHS] = reinterpret_cast<Stmt*>(Val);
+    updateContainsUnexpandedParameterPack();
+  }

   SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
   SourceLocation getLocEnd() const LLVM_READONLY {
@@ -750,8 +800,10 @@
 class DefaultStmt : public SwitchCase {
   Stmt* SubStmt;
 public:
-  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
-    SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
+  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt)
+    : SwitchCase(DefaultStmtClass, DL, CL,
+                 substmt->containsUnexpandedParameterPack()),
+      SubStmt(substmt) { }

   /// \brief Build an empty default statement.
   explicit DefaultStmt(EmptyShell Empty)
@@ -759,7 +811,10 @@

   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
-  void setSubStmt(Stmt *S) { SubStmt = S; }
+  void setSubStmt(Stmt *S) {
+    SubStmt = S;
+    setContainsUnexpandedParameterPack(S->containsUnexpandedParameterPack());
+  }

   SourceLocation getDefaultLoc() const { return KeywordLoc; }
   void setDefaultLoc(SourceLocation L) { KeywordLoc = L; }
@@ -793,7 +848,8 @@

 public:
   LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
-      : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
+      : Stmt(LabelStmtClass, substmt->containsUnexpandedParameterPack()),
+        IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
     static_assert(sizeof(LabelStmt) ==
                       2 * sizeof(SourceLocation) + 2 * sizeof(void *),
                   "LabelStmt too big");
@@ -835,8 +891,8 @@
   friend class ASTStmtReader;

   AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
-    : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
-      NumAttrs(Attrs.size()) {
+    : Stmt(AttributedStmtClass, SubStmt->containsUnexpandedParameterPack()),
+      SubStmt(SubStmt), AttrLoc(Loc), NumAttrs(Attrs.size()) {
     std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
   }

@@ -960,6 +1016,12 @@
   // values were covered by CaseStmts.  The coverage information value is meant
   // to be a hint for possible clients.
   llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
+  void updateContainsUnexpandedParameterPack() {
+    setContainsUnexpandedParameterPack(
+      (SubExprs[VAR] && SubExprs[VAR]->containsUnexpandedParameterPack()) ||
+      SubExprs[COND]->containsUnexpandedParameterPack() ||
+      (SubExprs[BODY] && SubExprs[BODY]->containsUnexpandedParameterPack()));
+  }

 public:
   SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond);
@@ -1004,6 +1066,7 @@
   void setBody(Stmt *S, SourceLocation SL) {
     SubExprs[BODY] = S;
     SwitchLoc = SL;
+    updateContainsUnexpandedParameterPack();
   }
   void addSwitchCase(SwitchCase *SC) {
     assert(!SC->getNextSwitchCase()
@@ -1103,7 +1166,10 @@
 public:
   DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL,
          SourceLocation RP)
-    : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
+    : Stmt(DoStmtClass,
+           (body->containsUnexpandedParameterPack() ||
+            reinterpret_cast<Stmt*>(cond)->containsUnexpandedParameterPack())),
+      DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
     SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
     SubExprs[BODY] = body;
   }
@@ -1221,7 +1287,7 @@
   SourceLocation LabelLoc;
 public:
   GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
-    : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
+    : Stmt(GotoStmtClass, false), Label(label), GotoLoc(GL), LabelLoc(LL) {}

   /// \brief Build an empty goto statement.
   explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
@@ -1256,7 +1322,7 @@
 public:
   IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
                    Expr *target)
-    : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
+    : Stmt(IndirectGotoStmtClass, false), GotoLoc(gotoLoc), StarLoc(starLoc),
       Target((Stmt*)target) {}

   /// \brief Build an empty indirect goto statement.
@@ -1296,7 +1362,8 @@
 class ContinueStmt : public Stmt {
   SourceLocation ContinueLoc;
 public:
-  ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
+  ContinueStmt(SourceLocation CL)
+    : Stmt(ContinueStmtClass, false), ContinueLoc(CL) {}

   /// \brief Build an empty continue statement.
   explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
@@ -1323,7 +1390,7 @@
   SourceLocation BreakLoc;

 public:
-  BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {
+  BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass, false), BreakLoc(BL) {
     static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation),
                   "BreakStmt too large");
   }
@@ -1366,8 +1433,8 @@
   explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}

   ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
-      : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
-        NRVOCandidate(NRVOCandidate) {}
+      : Stmt(ReturnStmtClass, ((Stmt *)E)->containsUnexpandedParameterPack()),
+        RetLoc(RL), RetExpr((Stmt *)E), NRVOCandidate(NRVOCandidate) {}

   /// \brief Build an empty return expression.
   explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
@@ -1424,7 +1491,7 @@

   AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile,
           unsigned numoutputs, unsigned numinputs, unsigned numclobbers) :
-    Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile),
+    Stmt(SC, false), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile),
     NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { }

   friend class ASTStmtReader;
@@ -1967,7 +2034,7 @@
   SourceLocation LeaveLoc;
 public:
   explicit SEHLeaveStmt(SourceLocation LL)
-      : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {}
+      : Stmt(SEHLeaveStmtClass, false), LeaveLoc(LL) {}

   /// \brief Build an empty __leave statement.
   explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { }
Index: include/clang/AST/StmtCXX.h
===================================================================
--- include/clang/AST/StmtCXX.h (revision 274740)
+++ include/clang/AST/StmtCXX.h (working copy)
@@ -35,11 +35,12 @@

 public:
   CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
-  : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
-    HandlerBlock(handlerBlock) {}
+  : Stmt(CXXCatchStmtClass, handlerBlock->containsUnexpandedParameterPack()),
+    CatchLoc(catchLoc), ExceptionDecl(exDecl), HandlerBlock(handlerBlock) {}

   CXXCatchStmt(EmptyShell Empty)
-  : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {}
+  : Stmt(CXXCatchStmtClass, Empty), ExceptionDecl(nullptr),
+    HandlerBlock(nullptr) {}

   SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
   SourceLocation getLocEnd() const LLVM_READONLY {
@@ -69,7 +70,7 @@
   CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);

   CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
-    : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
+    : Stmt(CXXTryStmtClass, Empty), NumHandlers(numHandlers) { }

   Stmt const * const *getStmts() const {
     return reinterpret_cast<Stmt const * const*>(this + 1);
@@ -135,6 +136,19 @@
   SourceLocation ColonLoc;
   SourceLocation RParenLoc;

+  void updateContainsUnexpandedParameterPack() {
+    setContainsUnexpandedParameterPack(
+      SubExprs[RANGE]->containsUnexpandedParameterPack() ||
+      (SubExprs[BEGINSTMT] &&
+                      SubExprs[BEGINSTMT]->containsUnexpandedParameterPack()) ||
+      (SubExprs[ENDSTMT] &&
+                      SubExprs[ENDSTMT]->containsUnexpandedParameterPack()) ||
+      (SubExprs[COND] && SubExprs[COND]->containsUnexpandedParameterPack()) ||
+      (SubExprs[INC] && SubExprs[INC]->containsUnexpandedParameterPack()) ||
+      SubExprs[LOOPVAR]->containsUnexpandedParameterPack() ||
+      (SubExprs[BODY] && SubExprs[BODY]->containsUnexpandedParameterPack()));
+  }
+
   friend class ASTStmtReader;
 public:
   CXXForRangeStmt(DeclStmt *Range, DeclStmt *Begin, DeclStmt *End,
@@ -188,7 +202,10 @@
   void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
   void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
   void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
-  void setBody(Stmt *S) { SubExprs[BODY] = S; }
+  void setBody(Stmt *S) {
+    SubExprs[BODY] = S;
+    updateContainsUnexpandedParameterPack();
+  }

   SourceLocation getForLoc() const { return ForLoc; }
   SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
@@ -210,6 +227,83 @@
   }
 };

+/// \brief Represents a C++11 pack expansion that produces a sequence of
+/// compound statements.
+///
+/// A pack expansion statement contains a pattern (which is a
+/// compond-statement) followed by an ellipsis. For example:
+///
+/// \code
+/// template<typename F,int... Is>
+/// void unroll(F f,index_sequence<Is...>) {
+///   { f(Is); }...
+/// }
+/// \endcode
+///
+/// Here, the argument to the function object \c f is a pack expansion whose
+/// pattern is \c static_cast<Types&&>(args). When the \c forward function
+/// template is instantiated, the pack expansion will instantiate to zero or
+/// or more function arguments to the function object \c f.
+class PackExpansionStmt : public Stmt {
+  SourceLocation EllipsisLoc;
+
+  /// \brief The number of expansions that will be produced by this pack
+  /// expansion statement, if known.
+  ///
+  /// When zero, the number of expansions is not known. Otherwise, this value
+  /// is the number of expansions + 1.
+  unsigned NumExpansions;
+
+  Stmt *Pattern;
+
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+
+public:
+  PackExpansionStmt(CompoundStmt *Pattern, SourceLocation EllipsisLoc,
+                    Optional<unsigned> NumExpansions)
+    : Stmt(PackExpansionStmtClass,
+           /*ContainsUnexpandedParameterPack=*/false),
+      EllipsisLoc(EllipsisLoc),
+      NumExpansions(NumExpansions? *NumExpansions + 1 : 0),
+      Pattern(Pattern) { }
+
+  PackExpansionStmt(EmptyShell Empty) : Stmt(PackExpansionStmtClass, Empty) { }
+
+  /// \brief Retrieve the pattern of the pack expansion.
+  CompoundStmt *getPattern() { return reinterpret_cast<CompoundStmt *>(Pattern); }
+
+  /// \brief Retrieve the pattern of the pack expansion.
+  const CompoundStmt *getPattern() const { return reinterpret_cast<CompoundStmt *>(Pattern); }
+
+  /// \brief Retrieve the location of the ellipsis that describes this pack
+  /// expansion.
+  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+  /// \brief Determine the number of expansions that will be produced when
+  /// this pack expansion is instantiated, if already known.
+  Optional<unsigned> getNumExpansions() const {
+    if (NumExpansions)
+      return NumExpansions - 1;
+
+    return None;
+  }
+
+  SourceLocation getLocStart() const LLVM_READONLY {
+    return Pattern->getLocStart();
+  }
+  SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == PackExpansionStmtClass;
+  }
+
+  // Iterators
+  child_range children() {
+    return child_range(&Pattern, &Pattern + 1);
+  }
+};
+
 /// \brief Representation of a Microsoft __if_exists or __if_not_exists
 /// statement with a dependent name.
 ///
@@ -252,7 +346,8 @@
                         NestedNameSpecifierLoc QualifierLoc,
                         DeclarationNameInfo NameInfo,
                         CompoundStmt *SubStmt)
-  : Stmt(MSDependentExistsStmtClass),
+  : Stmt(MSDependentExistsStmtClass,
+         SubStmt->containsUnexpandedParameterPack()),
     KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
     QualifierLoc(QualifierLoc), NameInfo(NameInfo),
     SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
@@ -314,7 +409,7 @@
   CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
                     Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
                     Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
-      : Stmt(CoroutineBodyStmtClass) {
+      : Stmt(CoroutineBodyStmtClass, /*containsUnexpandedParameterPack*/false) {
     SubStmts[CoroutineBodyStmt::Body] = Body;
     SubStmts[CoroutineBodyStmt::Promise] = Promise;
     SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
@@ -385,7 +480,10 @@
   friend class ASTStmtReader;
 public:
   CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
-      : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
+      : Stmt(CoreturnStmtClass,
+             (Operand->containsUnexpandedParameterPack() ||
+              PromiseCall->containsUnexpandedParameterPack())),
+        CoreturnLoc(CoreturnLoc) {
     SubStmts[SubStmt::Operand] = Operand;
     SubStmts[SubStmt::PromiseCall] = PromiseCall;
   }
Index: include/clang/AST/StmtObjC.h
===================================================================
--- include/clang/AST/StmtObjC.h (revision 274740)
+++ include/clang/AST/StmtObjC.h (working copy)
@@ -26,6 +26,12 @@
   Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
   SourceLocation ForLoc;
   SourceLocation RParenLoc;
+  void updateContainsUnexpandedParameterPack() {
+    setContainsUnexpandedParameterPack(
+      SubExprs[ELEM]->containsUnexpandedParameterPack() ||
+      SubExprs[COLLECTION]->containsUnexpandedParameterPack() ||
+      (SubExprs[BODY] && SubExprs[BODY]->containsUnexpandedParameterPack()));
+  }
 public:
   ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
                         SourceLocation FCL, SourceLocation RPL);
@@ -48,7 +54,10 @@
   void setCollection(Expr *E) {
     SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
   }
-  void setBody(Stmt *S) { SubExprs[BODY] = S; }
+  void setBody(Stmt *S) {
+    SubExprs[BODY] = S;
+    updateContainsUnexpandedParameterPack();
+  }

   SourceLocation getForLoc() const { return ForLoc; }
   void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
@@ -81,8 +90,10 @@
   ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
                   VarDecl *catchVarDecl,
                   Stmt *atCatchStmt)
-    : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
-    Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }
+    : Stmt(ObjCAtCatchStmtClass,
+           atCatchStmt->containsUnexpandedParameterPack()),
+      ExceptionDecl(catchVarDecl), Body(atCatchStmt),
+      AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }

   explicit ObjCAtCatchStmt(EmptyShell Empty) :
     Stmt(ObjCAtCatchStmtClass, Empty) { }
@@ -123,8 +134,9 @@

 public:
   ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
-      : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc),
-        AtFinallyStmt(atFinallyStmt) {}
+      : Stmt(ObjCAtFinallyStmtClass,
+             atFinallyStmt->containsUnexpandedParameterPack()),
+        AtFinallyLoc(atFinallyLoc), AtFinallyStmt(atFinallyStmt) {}

   explicit ObjCAtFinallyStmt(EmptyShell Empty) :
     Stmt(ObjCAtFinallyStmtClass, Empty) { }
@@ -214,6 +226,7 @@
     return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
   }

+// FIXME...
   /// \brief Set a particular catch statement.
   void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
     assert(I < NumCatchStmts && "Out-of-bounds @catch index");
@@ -268,7 +281,9 @@
 public:
   ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
                          Stmt *synchBody)
-  : Stmt(ObjCAtSynchronizedStmtClass) {
+  : Stmt(ObjCAtSynchronizedStmtClass,
+           (synchExpr->containsUnexpandedParameterPack() ||
+            synchBody->containsUnexpandedParameterPack())) {
     SubStmts[SYNC_EXPR] = synchExpr;
     SubStmts[SYNC_BODY] = synchBody;
     AtSynchronizedLoc = atSynchronizedLoc;
@@ -316,7 +331,8 @@

 public:
   ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
-  : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
+  : Stmt(ObjCAtThrowStmtClass,
+         throwExpr->containsUnexpandedParameterPack()), Throw(throwExpr) {
     AtThrowLoc = atThrowLoc;
   }
   explicit ObjCAtThrowStmt(EmptyShell Empty) :
@@ -348,7 +364,9 @@

 public:
   ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)
-      : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}
+      : Stmt(ObjCAutoreleasePoolStmtClass,
+             subStmt->containsUnexpandedParameterPack()),
+        AtLoc(atLoc), SubStmt(subStmt) {}

   explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
     Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
Index: include/clang/AST/StmtOpenMP.h
===================================================================
--- include/clang/AST/StmtOpenMP.h (revision 274740)
+++ include/clang/AST/StmtOpenMP.h (working copy)
@@ -67,7 +67,7 @@
   OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
                          SourceLocation StartLoc, SourceLocation EndLoc,
                          unsigned NumClauses, unsigned NumChildren)
-      : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
+      : Stmt(SC, false), Kind(K), StartLoc(std::move(StartLoc)),
         EndLoc(std::move(EndLoc)), NumClauses(NumClauses),
         NumChildren(NumChildren),
         ClausesOffset(llvm::alignTo(sizeof(T), llvm::alignOf<OMPClause *>())) {}
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td (revision 274740)
+++ include/clang/Basic/DiagnosticParseKinds.td (working copy)
@@ -693,6 +693,10 @@
 def err_fold_operator_mismatch : Error<
   "operators in fold expression must be the same">;

+def ext_stmt_expansion : Extension<
+  "block/statement pack expansion is a C++?? extension">,
+  InGroup<CXX1z>;
+
 def err_ctor_init_missing_comma : Error<
   "missing ',' between base or member initializers">;

Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td (revision 274740)
+++ include/clang/Basic/StmtNodes.td (working copy)
@@ -47,6 +47,7 @@
 def CXXCatchStmt : Stmt;
 def CXXTryStmt : Stmt;
 def CXXForRangeStmt : Stmt;
+def PackExpansionStmt : Stmt;

 // C++ Coroutines TS statements
 def CoroutineBodyStmt : Stmt;
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h (revision 274740)
+++ include/clang/Sema/Sema.h (working copy)
@@ -6258,6 +6258,14 @@
   void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
                          SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);

+  /// \brief Collect the set of unexpanded parameter packs within the given
+  /// statement.
+  ///
+  /// \param Arg The Statement that will be traversed to find unexpanded
+  /// parameter packs.
+  void collectUnexpandedParameterPacks(Stmt *Arg,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
   /// \brief Invoked when parsing a template argument followed by an
   /// ellipsis, which creates a pack expansion.
   ///
@@ -6309,6 +6317,25 @@
   ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
                                 Optional<unsigned> NumExpansions);

+  /// \brief Invoked when parsing a block followed by an ellipsis, which
+  /// creates a pack expansion.
+  ///
+  /// \param Pattern The compound statment preceding the ellipsis, which
+  /// will become the pattern of the pack expansion.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  StmtResult ActOnPackExpansion(Stmt *Pattern, SourceLocation EllipsisLoc);
+
+  /// \brief Invoked when parsing a block followed by an ellipsis, which
+  /// creates a pack expansion.
+  ///
+  /// \param Pattern The compound statment preceding the ellipsis, which
+  /// will become the pattern of the pack expansion.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  StmtResult CheckPackExpansion(Stmt *Pattern, SourceLocation EllipsisLoc,
+                                Optional<unsigned> NumExpansions);
+
   /// \brief Determine whether we could expand a pack expansion with the
   /// given set of parameter packs into separate arguments by repeatedly
   /// transforming the pattern.
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h (revision 274740)
+++ include/clang/Serialization/ASTBitCodes.h (working copy)
@@ -36,6 +36,7 @@
     /// Version 4 of AST files also requires that the version control branch and
     /// revision match exactly, since there is no backward compatibility of
     /// AST files at this time.
+// FIXME?
     const unsigned VERSION_MAJOR = 6;

     /// \brief AST file minor version number supported by this version of
@@ -1360,6 +1361,7 @@
       STMT_CXX_TRY,
       /// \brief A CXXForRangeStmt record.
       STMT_CXX_FOR_RANGE,
+      STMT_PACK_EXPANSION,        // PackExpansionStmt

       /// \brief A CXXOperatorCallExpr record.
       EXPR_CXX_OPERATOR_CALL,
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h (revision 274740)
+++ include/clang-c/Index.h (working copy)
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 35
+#define CINDEX_VERSION_MINOR 36

 #define CINDEX_VERSION_ENCODE(major, minor) ( \
       ((major) * 10000)                       \
@@ -2317,8 +2317,23 @@
    */
   CXCursor_OMPDistributeSimdDirective = 268,

-  CXCursor_LastStmt = CXCursor_OMPDistributeSimdDirective,
+  /** \brief Represents a C++0x pack expansion that produces a sequence of
+   * compound statements.
+   *
+   * A pack expansion statement contains a pattern (which is a
+   * compound-statement) followed by an ellipsis. For example:
+   *
+   * \code
+   * template<typename F,int... Is>
+   * void unroll(F f,index_sequence<Is...>) {
+   *   { f(Is); }...
+   * }
+   * \endcode
+   */
+  CXCursor_PackExpansionStmt             = 269,

+  CXCursor_LastStmt = CXCursor_PackExpansionStmt,
+
   /**
    * \brief Cursor that represents the translation unit itself.
    *
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp (revision 274740)
+++ lib/AST/ASTDumper.cpp (working copy)
@@ -1771,6 +1771,10 @@
   }
   dumpPointer(Node);
   dumpSourceRange(Node->getSourceRange());
+// FIXME... debug
+  if (Node->containsUnexpandedParameterPack()) {
+    OS << " hasUnexpandedPP";
+  }
 }

 void ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp (revision 274740)
+++ lib/AST/Expr.cpp (working copy)
@@ -314,9 +314,10 @@
   ExprBits.ValueDependent |= ValueDependent;
   ExprBits.InstantiationDependent |= InstantiationDependent;

+// FIXME   might *contain* one?  (getDecl() = NamedDecl)
   // Is the declaration a parameter pack?
   if (getDecl()->isParameterPack())
-    ExprBits.ContainsUnexpandedParameterPack = true;
+    setContainsUnexpandedParameterPack(true);
 }

 DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
@@ -337,7 +338,7 @@
     if (NNS->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (NNS->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);
   }
   DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
   if (FoundD)
@@ -355,7 +356,8 @@
         Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
     assert(!Dependent && "built a DeclRefExpr with dependent template args");
     ExprBits.InstantiationDependent |= InstantiationDependent;
-    ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
+    setContainsUnexpandedParameterPack(containsUnexpandedParameterPack() |
+                                       ContainsUnexpandedParameterPack);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1179,7 +1181,7 @@
   if (Arg->isInstantiationDependent())
     ExprBits.InstantiationDependent = true;
   if (Arg->containsUnexpandedParameterPack())
-    ExprBits.ContainsUnexpandedParameterPack = true;
+    setContainsUnexpandedParameterPack(true);
 }

 Decl *CallExpr::getCalleeDecl() {
@@ -1347,7 +1349,7 @@
     if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
       ExprBits.ValueDependent = true;
     if (exprs[i]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     setIndexExpr(i, exprs[i]);
   }
@@ -1779,7 +1781,7 @@
     if (initExprs[I]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (initExprs[I]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);
   }

   InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
@@ -3439,7 +3441,7 @@
     if (args[i]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (args[i]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SubExprs[i] = args[i];
   }
@@ -3550,7 +3552,7 @@
         ExprBits.InstantiationDependent = true;
       // Propagate unexpanded parameter packs.
       if (Index->containsUnexpandedParameterPack())
-        ExprBits.ContainsUnexpandedParameterPack = true;
+        setContainsUnexpandedParameterPack(true);

       // Copy the index expressions into permanent storage.
       *Child++ = IndexExprs[IndexIdx++];
@@ -3570,7 +3572,7 @@
       // Propagate unexpanded parameter packs.
       if (Start->containsUnexpandedParameterPack() ||
           End->containsUnexpandedParameterPack())
-        ExprBits.ContainsUnexpandedParameterPack = true;
+        setContainsUnexpandedParameterPack(true);

       // Copy the start/end expressions into permanent storage.
       *Child++ = IndexExprs[IndexIdx++];
@@ -3715,7 +3717,7 @@
     if (exprs[i]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (exprs[i]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     Exprs[i] = exprs[i];
   }
@@ -3789,7 +3791,7 @@
     if (E->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (E->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     if (isa<OpaqueValueExpr>(E))
       assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
@@ -3831,7 +3833,7 @@
     if (args[i]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (args[i]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SubExprs[i] = args[i];
   }
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp (revision 274740)
+++ lib/AST/ExprCXX.cpp (working copy)
@@ -88,7 +88,7 @@
       ExprBits.InstantiationDependent = true;

     if (arraySize->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SubExprs[i++] = arraySize;
   }
@@ -98,7 +98,7 @@
       ExprBits.InstantiationDependent = true;

     if (initializer->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SubExprs[i++] = initializer;
   }
@@ -107,7 +107,7 @@
     if (placementArgs[j]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (placementArgs[j]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SubExprs[i++] = placementArgs[j];
   }
@@ -308,7 +308,7 @@
     if (InstantiationDependent)
       ExprBits.InstantiationDependent = true;
     if (ContainsUnexpandedParameterPack)
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
   }
@@ -359,12 +359,11 @@
   if (Args) {
     bool Dependent = true;
     bool InstantiationDependent = true;
-    bool ContainsUnexpandedParameterPack
-      = ExprBits.ContainsUnexpandedParameterPack;
+    bool ContainsUnexpandedParameterPack = containsUnexpandedParameterPack();
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(),
         Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
-    ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+    setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -801,7 +800,7 @@
       if (Args[i]->isInstantiationDependent())
         ExprBits.InstantiationDependent = true;
       if (Args[i]->containsUnexpandedParameterPack())
-        ExprBits.ContainsUnexpandedParameterPack = true;
+        setContainsUnexpandedParameterPack(true);

       this->Args[i] = Args[i];
     }
@@ -1078,7 +1077,7 @@
   Expr **StoredArgs = getTrailingObjects<Expr *>();
   for (unsigned I = 0; I != Args.size(); ++I) {
     if (Args[I]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     StoredArgs[I] = Args[I];
   }
@@ -1132,7 +1131,7 @@
         TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
         Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
     if (ContainsUnexpandedParameterPack)
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
Index: lib/AST/ExprObjC.cpp
===================================================================
--- lib/AST/ExprObjC.cpp (revision 274740)
+++ lib/AST/ExprObjC.cpp (working copy)
@@ -29,7 +29,7 @@
     if (Elements[I]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (Elements[I]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     SaveElements[I] = Elements[I];
   }
@@ -71,7 +71,7 @@
     if (VK[I].EllipsisLoc.isInvalid() &&
         (VK[I].Key->containsUnexpandedParameterPack() ||
          VK[I].Value->containsUnexpandedParameterPack()))
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     KeyValues[I].Key = VK[I].Key;
     KeyValues[I].Value = VK[I].Value;
@@ -185,7 +185,7 @@
     if (Args[I]->isInstantiationDependent())
       ExprBits.InstantiationDependent = true;
     if (Args[I]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      setContainsUnexpandedParameterPack(true);

     MyArgs[I] = Args[I];
   }
Index: lib/AST/Stmt.cpp
===================================================================
--- lib/AST/Stmt.cpp (revision 274740)
+++ lib/AST/Stmt.cpp (working copy)
@@ -279,9 +279,20 @@
   llvm_unreachable("unknown statement kind");
 }

+// FIXME
+DeclStmt::DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
+                   SourceLocation endLoc)
+  : Stmt(DeclStmtClass, false), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {
+/* FIXME: DeclGroupRef .containsUnexpandedParameterPack()
+  // Is the declaration a parameter pack?
+  if (getDecl()->isParameterPack())
+    setContainsUnexpandedParameterPack(true);
+*/
+}
+
 CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
                            SourceLocation LB, SourceLocation RB)
-  : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {
+  : Stmt(CompoundStmtClass, false), LBraceLoc(LB), RBraceLoc(RB) {
   CompoundStmtBits.NumStmts = Stmts.size();
   assert(CompoundStmtBits.NumStmts == Stmts.size() &&
          "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
@@ -290,6 +301,10 @@
     Body = nullptr;
     return;
   }
+  for (unsigned i = 0; i != Stmts.size(); ++i) {
+    if (Stmts[i]->containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack(true);
+  }

   Body = new (C) Stmt*[Stmts.size()];
   std::copy(Stmts.begin(), Stmts.end(), Body);
@@ -766,12 +781,17 @@
 IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, bool IsConstexpr,
                VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL,
                Stmt *elsev)
-    : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) {
+    : Stmt(IfStmtClass, false), IfLoc(IL), ElseLoc(EL) {
   setConstexpr(IsConstexpr);
   setConditionVariable(C, var);
   SubExprs[COND] = cond;
   SubExprs[THEN] = then;
   SubExprs[ELSE] = elsev;
+  setContainsUnexpandedParameterPack(
+    (SubExprs[VAR] && SubExprs[VAR]->containsUnexpandedParameterPack()) ||
+    SubExprs[COND]->containsUnexpandedParameterPack() ||
+    SubExprs[THEN]->containsUnexpandedParameterPack() ||
+    (SubExprs[ELSE] && SubExprs[ELSE]->containsUnexpandedParameterPack()));
 }

 VarDecl *IfStmt::getConditionVariable() const {
@@ -796,7 +816,7 @@
 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
                  Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
                  SourceLocation RP)
-  : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
+  : Stmt(ForStmtClass, false), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
 {
   SubExprs[INIT] = Init;
   setConditionVariable(C, condVar);
@@ -803,6 +823,12 @@
   SubExprs[COND] = Cond;
   SubExprs[INC] = Inc;
   SubExprs[BODY] = Body;
+  setContainsUnexpandedParameterPack(
+    SubExprs[INIT]->containsUnexpandedParameterPack() ||
+    (SubExprs[CONDVAR] && SubExprs[CONDVAR]->containsUnexpandedParameterPack()) ||
+    SubExprs[COND]->containsUnexpandedParameterPack() ||
+    SubExprs[INC]->containsUnexpandedParameterPack() ||
+    SubExprs[BODY]->containsUnexpandedParameterPack());
 }

 VarDecl *ForStmt::getConditionVariable() const {
@@ -825,10 +851,11 @@
 }

 SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
-    : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
+    : Stmt(SwitchStmtClass, false), FirstCase(nullptr, false) {
   setConditionVariable(C, Var);
   SubExprs[COND] = cond;
   SubExprs[BODY] = nullptr;
+  updateContainsUnexpandedParameterPack();
 }

 VarDecl *SwitchStmt::getConditionVariable() const {
@@ -858,11 +885,15 @@

 WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
                      SourceLocation WL)
-  : Stmt(WhileStmtClass) {
+  : Stmt(WhileStmtClass, false) {
   setConditionVariable(C, Var);
   SubExprs[COND] = cond;
   SubExprs[BODY] = body;
   WhileLoc = WL;
+  setContainsUnexpandedParameterPack(
+    (SubExprs[VAR] && SubExprs[VAR]->containsUnexpandedParameterPack()) ||
+    SubExprs[COND]->containsUnexpandedParameterPack() ||
+    SubExprs[BODY]->containsUnexpandedParameterPack());
 }

 VarDecl *WhileStmt::getConditionVariable() const {
@@ -904,7 +935,9 @@
                        SourceLocation TryLoc,
                        Stmt *TryBlock,
                        Stmt *Handler)
-  : Stmt(SEHTryStmtClass),
+  : Stmt(SEHTryStmtClass,
+         (TryBlock->containsUnexpandedParameterPack() ||
+          Handler->containsUnexpandedParameterPack())),
     IsCXXTry(IsCXXTry),
     TryLoc(TryLoc)
 {
@@ -929,7 +962,9 @@
 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc,
                              Expr *FilterExpr,
                              Stmt *Block)
-  : Stmt(SEHExceptStmtClass),
+  : Stmt(SEHExceptStmtClass,
+         (FilterExpr->containsUnexpandedParameterPack() ||
+          Block->containsUnexpandedParameterPack())),
     Loc(Loc)
 {
   Children[FILTER_EXPR] = FilterExpr;
@@ -943,7 +978,7 @@

 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc,
                                Stmt *Block)
-  : Stmt(SEHFinallyStmtClass),
+  : Stmt(SEHFinallyStmtClass, Block->containsUnexpandedParameterPack()),
     Loc(Loc),
     Block(Block)
 {}
@@ -953,6 +988,7 @@
   return new(C)SEHFinallyStmt(Loc,Block);
 }

+// FIXME
 CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
                                VarDecl *Var)
     : VarAndKind(Var, Kind), Loc(Loc) {
@@ -1002,17 +1038,20 @@
       + FirstCaptureOffset);
 }

+// FIXME
 CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
                            ArrayRef<Capture> Captures,
                            ArrayRef<Expr *> CaptureInits,
                            CapturedDecl *CD,
                            RecordDecl *RD)
-  : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
+  : Stmt(CapturedStmtClass, false), NumCaptures(Captures.size()),
     CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
   assert( S && "null captured statement");
   assert(CD && "null captured declaration for captured statement");
   assert(RD && "null record declaration for captured statement");

+// FIXME  setContainsUnexpandedParameterPack(...);
+
   // Copy initialization expressions.
   Stmt **Stored = getStoredStmts();
   for (unsigned I = 0, N = NumCaptures; I != N; ++I)
Index: lib/AST/StmtCXX.cpp
===================================================================
--- lib/AST/StmtCXX.cpp (revision 274740)
+++ lib/AST/StmtCXX.cpp (working copy)
@@ -43,7 +43,13 @@

 CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
                        ArrayRef<Stmt *> handlers)
-    : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) {
+    : Stmt(CXXTryStmtClass, false), TryLoc(tryLoc),
+      NumHandlers(handlers.size()) {
+  for (unsigned i = 0; i != handlers.size(); ++i) {
+    if (handlers[i]->containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack(true);
+  }
+
   Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
   Stmts[0] = tryBlock;
   std::copy(handlers.begin(), handlers.end(), Stmts + 1);
@@ -55,7 +61,7 @@
                                  Stmt *Body, SourceLocation FL,
                                  SourceLocation CAL, SourceLocation CL,
                                  SourceLocation RPL)
-    : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL),
+    : Stmt(CXXForRangeStmtClass, false), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL),
       RParenLoc(RPL) {
   SubExprs[RANGE] = Range;
   SubExprs[BEGINSTMT] = BeginStmt;
@@ -64,6 +70,7 @@
   SubExprs[INC] = Inc;
   SubExprs[LOOPVAR] = LoopVar;
   SubExprs[BODY] = Body;
+  updateContainsUnexpandedParameterPack();
 }

 Expr *CXXForRangeStmt::getRangeInit() {
Index: lib/AST/StmtObjC.cpp
===================================================================
--- lib/AST/StmtObjC.cpp (revision 274740)
+++ lib/AST/StmtObjC.cpp (working copy)
@@ -21,19 +21,23 @@
 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
                                              Stmt *Body, SourceLocation FCL,
                                              SourceLocation RPL)
-    : Stmt(ObjCForCollectionStmtClass) {
+    : Stmt(ObjCForCollectionStmtClass, false) {
   SubExprs[ELEM] = Elem;
   SubExprs[COLLECTION] = Collect;
   SubExprs[BODY] = Body;
   ForLoc = FCL;
   RParenLoc = RPL;
+  updateContainsUnexpandedParameterPack();
 }

 ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
                              Stmt **CatchStmts, unsigned NumCatchStmts,
                              Stmt *atFinallyStmt)
-    : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
-      NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) {
+    : Stmt(ObjCAtTryStmtClass,
+           (atTryStmt->containsUnexpandedParameterPack() ||
+            (atFinallyStmt && atFinallyStmt->containsUnexpandedParameterPack()))),
+      AtTryLoc(atTryLoc), NumCatchStmts(NumCatchStmts),
+      HasFinally(atFinallyStmt != nullptr) {
   Stmt **Stmts = getStmts();
   Stmts[0] = atTryStmt;
   for (unsigned I = 0; I != NumCatchStmts; ++I)
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp (revision 274740)
+++ lib/AST/StmtPrinter.cpp (working copy)
@@ -323,6 +323,11 @@
   if (Policy.IncludeNewlines) OS << "\n";
 }

+void StmtPrinter::VisitPackExpansionStmt(PackExpansionStmt *Node) {
+  PrintStmt(Node->getPattern());
+  OS << "...";
+}
+
 void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
   Indent();
   if (Node->isIfExists())
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp (revision 274740)
+++ lib/AST/StmtProfile.cpp (working copy)
@@ -197,6 +197,10 @@
   VisitStmt(S);
 }

+void StmtProfiler::VisitPackExpansionStmt(const PackExpansionStmt *S) {
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) {
   VisitStmt(S);
   ID.AddBoolean(S->isIfExists());
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp (revision 274740)
+++ lib/CodeGen/CGStmt.cpp (working copy)
@@ -79,6 +79,7 @@
   case Stmt::CXXCatchStmtClass:
   case Stmt::SEHExceptStmtClass:
   case Stmt::SEHFinallyStmtClass:
+  case Stmt::PackExpansionStmtClass:
   case Stmt::MSDependentExistsStmtClass:
     llvm_unreachable("invalid statement class to emit generically");
   case Stmt::NullStmtClass:
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp (revision 274740)
+++ lib/Parse/ParseStmt.cpp (working copy)
@@ -57,6 +57,7 @@
 ///       statement:
 ///         labeled-statement
 ///         compound-statement
+/// [C++?]  compound-statement '...'
 ///         expression-statement
 ///         selection-statement
 ///         iteration-statement
@@ -230,8 +231,17 @@
   case tok::kw_default:             // C99 6.8.1: labeled-statement
     return ParseDefaultStatement();

-  case tok::l_brace:                // C99 6.8.2: compound-statement
-    return ParseCompoundStatement();
+  case tok::l_brace: {              // C99 6.8.2: compound-statement
+    Res = ParseCompoundStatement();
+    if (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis)) {
+      SourceLocation EllipsisLoc = ConsumeToken();
+      Diag(EllipsisLoc, diag::ext_stmt_expansion);
+      if (Res.isUsable())
+        return Actions.ActOnPackExpansion(Res.get(), EllipsisLoc);
+    }
+    return Res;
+  }
+
   case tok::semi: {                 // C99 6.8.3p3: expression[opt] ';'
     bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
     return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
@@ -856,7 +866,7 @@
 ///
 StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
                                           unsigned ScopeFlags) {
-  assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
+  assert(Tok.is(tok::l_brace) && "Not a compound stmt!");

   // Enter a scope to hold everything within the compound stmt.  Compound
   // statements can always hold declarations.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp (revision 274740)
+++ lib/Sema/SemaDecl.cpp (working copy)
@@ -11455,6 +11455,8 @@
   sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
   sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;

+// FIXME? assert(!Body->containsUnexpandedParameterPack());  - Diagnostic needed earlier!
+
   if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
     CheckCompletedCoroutineBody(FD, Body);

Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp (revision 274740)
+++ lib/Sema/SemaExprCXX.cpp (working copy)
@@ -6999,9 +6999,11 @@
   // lambda where we've entered the introducer but not the body, or represent a
   // lambda where we've entered the body, depending on where the
   // parser/instantiation has got to).
+/* FIXME...  - parameter packs may escape expression, but not function/body
   if (!IsLambdaInitCaptureInitializer &&
       DiagnoseUnexpandedParameterPack(FullExpr.get()))
     return ExprError();
+*/

   // Top-level expressions default to 'id' when we're in a debugger.
   if (DiscardedValue && getLangOpts().DebuggerCastResultToId &&
Index: lib/Sema/SemaTemplateVariadic.cpp
===================================================================
--- lib/Sema/SemaTemplateVariadic.cpp (revision 274740)
+++ lib/Sema/SemaTemplateVariadic.cpp (working copy)
@@ -73,6 +73,7 @@
     bool VisitDeclRefExpr(DeclRefExpr *E) {
       if (E->getDecl()->isParameterPack())
         Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+// FIXME? DeclRef -> init?  (?? containsPack?)

       return true;
     }
@@ -110,9 +111,8 @@

     /// \brief Suppress traversal into statements and expressions that
     /// do not contain unexpanded parameter packs.
-    bool TraverseStmt(Stmt *S) {
-      Expr *E = dyn_cast_or_null<Expr>(S);
-      if ((E && E->containsUnexpandedParameterPack()) || InLambda)
+    bool TraverseStmt(Stmt *S) {
+      if ((S && S->containsUnexpandedParameterPack()) || InLambda)
         return inherited::TraverseStmt(S);

       return true;
@@ -159,6 +159,7 @@
     bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
       if (ArgLoc.getArgument().isPackExpansion())
         return true;
+// FIXME?  is this still the right thing to do for Expressions (?? .isExpression && .containsUnexpanded ?)

       return inherited::TraverseTemplateArgumentLoc(ArgLoc);
     }
@@ -177,6 +178,7 @@
       bool WasInLambda = InLambda;
       InLambda = true;

+// FIXME?
       // If any capture names a function parameter pack, that pack is expanded
       // when the lambda is expanded.
       for (LambdaExpr::capture_iterator I = Lambda->capture_begin(),
@@ -279,6 +281,7 @@

 bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
                                         UnexpandedParameterPackContext UPPC) {
+// FIXME  (hack: commented out in SemaExprCXX.cpp)
   // C++0x [temp.variadic]p5:
   //   An appearance of a name of a parameter pack that is not expanded is
   //   ill-formed.
@@ -409,6 +412,11 @@
     .TraverseDeclarationNameInfo(NameInfo);
 }

+void Sema::collectUnexpandedParameterPacks(Stmt *Arg,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseStmt(Arg);
+}

 ParsedTemplateArgument
 Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
@@ -522,6 +530,28 @@
     PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions);
 }

+StmtResult Sema::ActOnPackExpansion(Stmt *Pattern, SourceLocation EllipsisLoc) {
+  return CheckPackExpansion(Pattern, EllipsisLoc, None);
+}
+
+StmtResult Sema::CheckPackExpansion(Stmt *Pattern, SourceLocation EllipsisLoc,
+                                    Optional<unsigned> NumExpansions) {
+  CompoundStmt *CSPattern=cast<CompoundStmt>(Pattern);
+
+  // FIXME: C++?? [temp.variadic??]p??:
+  //   The pattern of a pack expansion shall name one or more
+  //   parameter packs that are not expanded by a nested pack
+  //   expansion.
+  if (!CSPattern->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+    << CSPattern->getSourceRange();
+    return StmtError();
+  }
+
+  // Create the pack expansion block and source-location information.
+  return new (Context) PackExpansionStmt(CSPattern, EllipsisLoc, NumExpansions);
+}
+
 /// \brief Retrieve the depth and index of a parameter pack.
 static std::pair<unsigned, unsigned>
 getDepthAndIndex(NamedDecl *ND) {
@@ -917,6 +947,17 @@
     return TemplateArgumentLoc(Pattern, Pattern);
   }

+/* FIXME
+  case TemplateArgument::CompoundStatement: {
+    PackExpansionStmt *Expansion
+      = cast<PackExpansionStmt>(Argument.getAsStmt());
+    Stmt *Pattern = Expansion->getPattern();
+    Ellipsis = Expansion->getEllipsisLoc();
+    NumExpansions = Expansion->getNumExpansions();
+    return TemplateArgumentLoc(Pattern, Pattern);
+  }
+*/
+
   case TemplateArgument::TemplateExpansion:
     Ellipsis = OrigLoc.getTemplateEllipsisLoc();
     NumExpansions = Argument.getNumTemplateExpansions();
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h (revision 274740)
+++ lib/Sema/TreeTransform.h (working copy)
@@ -3061,6 +3061,16 @@
     return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
   }

+  /// \brief Build a new statment pack expansion.
+  ///
+  /// By default, performs semantic analysis to build a new pack expansion
+  /// for a statment. Subclasses may override this routine to provide
+  /// different behavior.
+  StmtResult RebuildPackExpansion(Stmt *Pattern, SourceLocation EllipsisLoc,
+                                  Optional<unsigned> NumExpansions) {
+    return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
+  }
+
   /// \brief Build a new C++1z fold-expression.
   ///
   /// By default, performs semantic analysis in order to build a new fold
@@ -3278,7 +3288,7 @@
       Expr *Pattern = Expansion->getPattern();

       SmallVector<UnexpandedParameterPack, 2> Unexpanded;
-      getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); // FIXME/TODO? use (Stmt *)Pattern?
       assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");

       // Determine whether the set of unexpanded parameter packs can and should
@@ -6953,6 +6963,85 @@

 template<typename Derived>
 StmtResult
+TreeTransform<Derived>::TransformPackExpansionStmt(PackExpansionStmt *S) {
+  CompoundStmt *Pattern = S->getPattern();
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+  assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+  // Determine whether the set of unexpanded parameter packs can and should
+  // be expanded.
+  bool Expand = true;
+  bool RetainExpansion = false;
+  Optional<unsigned> OrigNumExpansions = S->getNumExpansions();
+  Optional<unsigned> NumExpansions = OrigNumExpansions;
+  if (getDerived().TryExpandParameterPacks(S->getEllipsisLoc(),
+                                           Pattern->getSourceRange(),
+                                           Unexpanded, Expand, RetainExpansion,
+                                           NumExpansions))
+    return StmtError();
+
+  if (!Expand) {
+    // Do not expand the packs here, just transform and rebuild
+    // the pack expansion.
+    Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+    StmtResult OutPattern = getDerived().TransformStmt(Pattern);
+    if (OutPattern.isInvalid())
+      return StmtError();
+
+    if (!getDerived().AlwaysRebuild() && OutPattern.get() == S->getPattern())
+      return S;
+
+    return getDerived().RebuildPackExpansion(OutPattern.get(),
+                                             S->getEllipsisLoc(),
+                                             NumExpansions);
+  }
+
+  SmallVector<Stmt*, 8> Statements;
+  // The transform has determined that we should perform an elementwise
+  // expansion of the pattern. Do so.
+  for (unsigned I = 0; I != *NumExpansions; ++I) {
+    Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+
+    StmtResult Out = getDerived().TransformStmt(Pattern);
+    if (Out.isInvalid())
+      return StmtError();
+
+// FIXME?  does this still make sense?
+    if (Out.get()->containsUnexpandedParameterPack()) {
+      Out = getDerived().RebuildPackExpansion(
+          Out.get(), S->getEllipsisLoc(), OrigNumExpansions);
+      if (Out.isInvalid())
+        return StmtError();
+    }
+    Statements.push_back(Out.get());
+  }
+
+// FIXME?  does this still make sense here?
+  // If we're supposed to retain a pack expansion, do so by temporarily
+  // forgetting the partially-substituted parameter pack.
+  if (RetainExpansion) {
+    ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+    StmtResult Out = getDerived().TransformStmt(Pattern);
+    if (Out.isInvalid())
+      return StmtError();
+
+    Out = getDerived().RebuildPackExpansion(
+        Out.get(), S->getEllipsisLoc(), OrigNumExpansions);
+
+    Statements.push_back(Out.get());
+  }
+
+  return getDerived().RebuildCompoundStmt(Pattern->getLBracLoc(),
+                                          Statements,
+                                          S->getEllipsisLoc(),
+                                          false);
+}
+
+template<typename Derived>
+StmtResult
 TreeTransform<Derived>::TransformMSDependentExistsStmt(
                                                     MSDependentExistsStmt *S) {
   // Transform the nested-name-specifier, if any.
@@ -10693,7 +10782,7 @@
   Expr *Pattern = E->getPattern();

   SmallVector<UnexpandedParameterPack, 2> Unexpanded;
-  getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+  getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);  // FIXME/TODO? use (Stmt *)Pattern
   assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");

   // Determine whether the set of unexpanded parameter packs can and should
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp (revision 274740)
+++ lib/Serialization/ASTReaderStmt.cpp (working copy)
@@ -120,6 +120,7 @@
 }

 void ASTStmtReader::VisitStmt(Stmt *S) {
+  S->StmtBits.ContainsUnexpandedParameterPack = Record[Idx++];
   assert(Idx == NumStmtFields && "Incorrect statement field count");
 }

@@ -435,7 +436,6 @@
   E->setTypeDependent(Record[Idx++]);
   E->setValueDependent(Record[Idx++]);
   E->setInstantiationDependent(Record[Idx++]);
-  E->ExprBits.ContainsUnexpandedParameterPack = Record[Idx++];
   E->setValueKind(static_cast<ExprValueKind>(Record[Idx++]));
   E->setObjectKind(static_cast<ExprObjectKind>(Record[Idx++]));
   assert(Idx == NumExprFields && "Incorrect expression field count");
@@ -1216,6 +1216,13 @@
   S->setBody(Reader.ReadSubStmt());
 }

+void ASTStmtReader::VisitPackExpansionStmt(PackExpansionStmt *S) {
+  VisitStmt(S);
+  S->EllipsisLoc = ReadSourceLocation(Record, Idx);
+  S->NumExpansions = Record[Idx++];
+  S->Pattern = Reader.ReadSubStmt();
+}
+
 void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
   VisitStmt(S);
   S->KeywordLoc = ReadSourceLocation(Record, Idx);
@@ -3211,6 +3218,10 @@
       S = new (Context) CXXForRangeStmt(Empty);
       break;

+    case STMT_PACK_EXPANSION:
+      S = new (Context) PackExpansionStmt(Empty);
+      break;
+
     case STMT_MS_DEPENDENT_EXISTS:
       S = new (Context) MSDependentExistsStmt(SourceLocation(), true,
                                               NestedNameSpecifierLoc(),
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp (revision 274740)
+++ lib/Serialization/ASTWriter.cpp (working copy)
@@ -854,6 +854,7 @@
   RECORD(STMT_CXX_CATCH);
   RECORD(STMT_CXX_TRY);
   RECORD(STMT_CXX_FOR_RANGE);
+  RECORD(STMT_PACK_EXPANSION);
   RECORD(EXPR_CXX_OPERATOR_CALL);
   RECORD(EXPR_CXX_MEMBER_CALL);
   RECORD(EXPR_CXX_CONSTRUCT);
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp (revision 274740)
+++ lib/Serialization/ASTWriterDecl.cpp (working copy)
@@ -2014,12 +2014,12 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF));
   //Stmt
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   //Expr
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
   //DeclRefExpr
@@ -2037,12 +2037,12 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL));
   //Stmt
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   //Expr
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
   //Integer Literal
@@ -2055,12 +2055,12 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL));
   //Stmt
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   //Expr
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
   //Character Literal
@@ -2073,12 +2073,12 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST));
   // Stmt
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   // Expr
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
   // CastExpr
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp (revision 274740)
+++ lib/Serialization/ASTWriterStmt.cpp (working copy)
@@ -68,6 +68,7 @@
 }

 void ASTStmtWriter::VisitStmt(Stmt *S) {
+  Record.push_back(S->containsUnexpandedParameterPack());
 }

 void ASTStmtWriter::VisitNullStmt(NullStmt *S) {
@@ -355,7 +356,6 @@
   Record.push_back(E->isTypeDependent());
   Record.push_back(E->isValueDependent());
   Record.push_back(E->isInstantiationDependent());
-  Record.push_back(E->containsUnexpandedParameterPack());
   Record.push_back(E->getValueKind());
   Record.push_back(E->getObjectKind());
 }
@@ -1178,6 +1178,14 @@
   Code = serialization::STMT_CXX_FOR_RANGE;
 }

+void ASTStmtWriter::VisitPackExpansionStmt(PackExpansionStmt *S) {
+  VisitStmt(S);
+  Record.AddSourceLocation(S->getEllipsisLoc());
+  Record.push_back(S->NumExpansions);
+  Record.AddStmt(S->getPattern());
+  Code = serialization::STMT_PACK_EXPANSION;
+}
+
 void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
   VisitStmt(S);
   Record.AddSourceLocation(S->getKeywordLoc());
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp (revision 274740)
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp (working copy)
@@ -806,6 +806,7 @@
     case Stmt::LabelStmtClass:
     case Stmt::NoStmtClass:
     case Stmt::NullStmtClass:
+    case Stmt::PackExpansionStmtClass:
     case Stmt::SwitchStmtClass:
     case Stmt::WhileStmtClass:
     case Expr::MSDependentExistsStmtClass:
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp (revision 274740)
+++ tools/libclang/CIndex.cpp (working copy)
@@ -4682,6 +4682,8 @@
       return cxstring::createRef("CXXTryStmt");
   case CXCursor_CXXForRangeStmt:
       return cxstring::createRef("CXXForRangeStmt");
+  case CXCursor_PackExpansionStmt:
+      return cxstring::createRef("PackExpansionStmt");
   case CXCursor_SEHTryStmt:
       return cxstring::createRef("SEHTryStmt");
   case CXCursor_SEHExceptStmt:
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp (revision 274740)
+++ tools/libclang/CXCursor.cpp (working copy)
@@ -207,6 +207,10 @@
   case Stmt::CXXForRangeStmtClass:
     K = CXCursor_CXXForRangeStmt;
     break;
+
+  case Stmt::PackExpansionStmtClass:
+    K = CXCursor_PackExpansionStmt;
+    break;

   case Stmt::SEHTryStmtClass:
     K = CXCursor_SEHTryStmt;

------=_Part_4176_43500046.1467896025836--

.


Author: =?UTF-8?Q?Micha=C5=82_Dominiak?= <griwes@griwes.info>
Date: Thu, 07 Jul 2016 13:05:19 +0000
Raw View
--001a114ba97a12cb3f05370b573d
Content-Type: text/plain; charset=UTF-8

On Thu, Jul 7, 2016 at 2:53 PM smilingthax via ISO C++ Standard - Future
Proposals <std-proposals@isocpp.org> wrote:

> On Wednesday, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bolas wrote:
>>
>> Things don't get standardized because someone posts a suggestion in a
>> mailing list. Things get standardized because someone puts work and effort
>> into it, pushing it forward at actual standards meetings.
>>
>
> Sure. But not all of us are in a position to participate in standards
> meetings.
>

You don't need to participate in a meeting yourself; all you'd need to do
is 1) write a paper (and yes, this is considered effort, and if you really
want something, you should put that effort into it), and 2) find somebody
to champion the proposal. You are saying there's a lot of people wanting
this (frankly I agree, myself included), which should mean that finding a
champion for this shouldn't be very hard.

But the very first step in finding a champion is actually writing a paper,
so that people may look at what is the actual thing you are proposing,
what's the rationale, what problems it solves, ..., and possibly get
interested in it.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPCFJdRCyTnQbVxMoxtbjVsw-d9eBXgkZW9irL1G%2BGxVWXo4Tg%40mail.gmail.com.

--001a114ba97a12cb3f05370b573d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Thu, Jul 7,=
 2016 at 2:53 PM smilingthax via ISO C++ Standard - Future Proposals &lt;<a=
 href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>&gt; =
wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesda=
y, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bolas wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><div>Things don&#39;t get standardized=
 because someone posts a suggestion in a mailing list. Things get standardi=
zed because someone puts work and effort into it, pushing it forward at act=
ual standards meetings.<br></div></div></blockquote><div><br></div></div><d=
iv dir=3D"ltr"><div>Sure. But not all of us are in a position to participat=
e in standards meetings.</div></div></blockquote><div>=C2=A0</div><div>You =
don&#39;t need to participate in a meeting yourself; all you&#39;d need to =
do is 1) write a paper (and yes, this is considered effort, and if you real=
ly want something, you should put that effort into it), and 2) find somebod=
y to champion the proposal. You are saying there&#39;s a lot of people want=
ing this (frankly I agree, myself included), which should mean that finding=
 a champion for this shouldn&#39;t be very hard.</div><div><br></div><div>B=
ut the very first step in finding a champion is actually writing a paper, s=
o that people may look at what is the actual thing you are proposing, what&=
#39;s the rationale, what problems it solves, ..., and possibly get interes=
ted in it.</div></div></div>

<p></p>

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

--001a114ba97a12cb3f05370b573d--

.


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 7 Jul 2016 06:08:33 -0700 (PDT)
Raw View
------=_Part_352_947149777.1467896913696
Content-Type: multipart/alternative;
 boundary="----=_Part_353_220462876.1467896913696"

------=_Part_353_220462876.1467896913696
Content-Type: text/plain; charset=UTF-8

On Thursday, July 7, 2016 at 8:33:50 AM UTC+2, Sergey Vidyuk wrote:
>
>
>>> At least, I'd be helpful to have SOME guidance from the standardization
>>> body, whether they prefer such a simple solution or whether they'd like
>>> more work done on "for constexpr"(e.g.).
>>>
>> And, if block/statement expansion won't move forward (for now), maybe add
>>> a more specific expansion for switch/case (something akin to the "first
>>> syntax idea" from my first mail)?
>>>
>>
> some info on for constexpr discussed here:
> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
> Right now I'm playing with gcc code (using my free time so progress is not
> rapid enough). I want to have implementation I can play with and share with
> other people on this list and then start to work on proposal paper.
>
>
What I don't like with for constexpr is that it does not work so well with
switch/case, because it changes the destinations of continue/break. Also
IMHO the syntax is quite verbose.
Some kind of inplace - template/type destructuring would be nice, but you
quickly get to the point of wanting the full matching power of partial
template specialization. So that would certainly be too much complexity.

Also note that some of the for constexpr can already be achieved by
fold-expressions. Except for goto/return, that is:

template <typename T> struct type_c { typedef T type; };

template <typename... Ts> // ...
  ([&](auto t){
     using T=typename decltype(t)::type;
     //... instead of "continue;" -> "return true;"
     //... instead of "break;" -> "return false;"
     return true; // must be inserted at the end
   }(type_c<Ts>()) && ... );

A similar transform is possible for non-type parameter packs.

  Tobias

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2c5dbd16-d2c0-4a29-a64b-70b6425f3c55%40isocpp.org.

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

<div dir=3D"ltr">On Thursday, July 7, 2016 at 8:33:50 AM UTC+2, Sergey Vidy=
uk wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><blockquote class=3D"=
gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid=
;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><br><div>At least, I&#39;d be helpful to have SOME guidan=
ce from the standardization body, whether they prefer such a simple solutio=
n or whether they&#39;d like more work done on &quot;for constexpr&quot;(e.=
g.).=C2=A0<br></div></div></blockquote></div></blockquote><div></div><block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>And, if=C2=A0block/statement expansio=
n won&#39;t move forward (for now), maybe=C2=A0add a more specific expansio=
n for switch/case (something akin to the &quot;first syntax idea&quot; from=
 my first mail)?</div></div></blockquote></div></blockquote><div><br>some i=
nfo on for constexpr discussed here:=20
<a href=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/=
std-proposals/2hdpLnXJKkQ" target=3D"_blank" rel=3D"nofollow" onmousedown=
=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgrou=
ps#!topic/std-proposals/2hdpLnXJKkQ&#39;;return true;" onclick=3D"this.href=
=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std=
-proposals/2hdpLnXJKkQ&#39;;return true;">https://groups.google.com/a/<wbr>=
isocpp.org/forum/?fromgroups#!<wbr>topic/std-proposals/<wbr>2hdpLnXJKkQ</a>
 Right now I&#39;m playing with gcc code (using my free time so progress is=
=20
not rapid enough). I want to have implementation I can play with and=20
share=20
with other people on this list and then start to work on proposal paper.<br=
><br></div></blockquote><div><div><br></div><div>What I don&#39;t like with=
 for constexpr is that it does not work so well with switch/case, because i=
t changes the destinations of continue/break. Also IMHO the syntax is quite=
 verbose.</div><div>Some kind of inplace - template/type destructuring woul=
d be nice, but you quickly get to the point of wanting the full matching po=
wer of partial template specialization. So that would certainly be too much=
 complexity.</div><div><br></div><div>Also note that some of the for conste=
xpr can already be achieved by fold-expressions. Except for goto/return, th=
at is:<br><br></div><div class=3D"prettyprint" style=3D"border: 1px solid r=
gb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 2=
50);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><font color=
=3D"#000000"><span style=3D"color: #008;" class=3D"styled-by-prettify">temp=
late</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> type_c </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">typedef</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> T type</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span></font><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">template</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">typename</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">...</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">([&amp;](</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> t</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">){</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">using</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">decltype</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">):=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">type</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>=C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">//... inst=
ead of &quot;continue;&quot; -&gt; &quot;return true;&quot;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">//... instea=
d of &quot;break;&quot; -&gt; &quot;return false;&quot;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">true</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// must be inserted at the end</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">type_c</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&gt;())</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&amp;&amp;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</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><div><br></div></div>A similar transform is possible for non-ty=
pe parameter packs.<br><br>=C2=A0 Tobias</div>

<p></p>

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

------=_Part_353_220462876.1467896913696--

------=_Part_352_947149777.1467896913696--

.


Author: inkwizytoryankes@gmail.com
Date: Thu, 7 Jul 2016 07:29:04 -0700 (PDT)
Raw View
------=_Part_5857_813396084.1467901744915
Content-Type: multipart/alternative;
 boundary="----=_Part_5858_1734611478.1467901744917"

------=_Part_5858_1734611478.1467901744917
Content-Type: text/plain; charset=UTF-8



On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, smili...@googlemail.com
wrote:
>
> On Thursday, July 7, 2016 at 8:33:50 AM UTC+2, Sergey Vidyuk wrote:
>>
>>
>>>> At least, I'd be helpful to have SOME guidance from the standardization
>>>> body, whether they prefer such a simple solution or whether they'd like
>>>> more work done on "for constexpr"(e.g.).
>>>>
>>> And, if block/statement expansion won't move forward (for now),
>>>> maybe add a more specific expansion for switch/case (something akin to the
>>>> "first syntax idea" from my first mail)?
>>>>
>>>
>> some info on for constexpr discussed here:
>> https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/2hdpLnXJKkQ
>> Right now I'm playing with gcc code (using my free time so progress is not
>> rapid enough). I want to have implementation I can play with and share with
>> other people on this list and then start to work on proposal paper.
>>
>>
> What I don't like with for constexpr is that it does not work so well with
> switch/case, because it changes the destinations of continue/break. Also
> IMHO the syntax is quite verbose.
> Some kind of inplace - template/type destructuring would be nice, but you
> quickly get to the point of wanting the full matching power of partial
> template specialization. So that would certainly be too much complexity.
>
> Also note that some of the for constexpr can already be achieved by
> fold-expressions. Except for goto/return, that is:
>
> template <typename T> struct type_c { typedef T type; };
>
> template <typename... Ts> // ...
>   ([&](auto t){
>      using T=typename decltype(t)::type;
>      //... instead of "continue;" -> "return true;"
>      //... instead of "break;" -> "return false;"
>      return true; // must be inserted at the end
>    }(type_c<Ts>()) && ... );
>
> A similar transform is possible for non-type parameter packs.
>
>   Tobias
>
Yes, `for constexpr` is far more verbose but this give us lot more control
over that happens. Dots work great when you want expand one parameter pack
but if is more of them or you want start do some complex thing this will
start be problematic.
Image you want use Cartesian product of two parameters pack. Without
introducing completely new syntax you can't handle it. Of corse `for` have
limitation too, but is lot of easier remove it.
Only thing that `for constexpr` need to handle nearly all possible use
cases is allow it to extract template parameters from concrete templates
(it would need have parameters like `template<typename... T>` or
`template<auto... A>`):
// we have two packs, T1 and T2
template<typename...> pack{};

for constexpr (typename A : pack<T1..., T2...>) { } //pack merge
for constexpr (typename A : typename zip<pack<T1...>, pack<T2...>>::type) {
} //zip two parameters pack, `type` is `pack<std::pair<T1, T2>...>`
for constexpr (typename A : pack<T1...>) { for constexpr (typename B : pack<
T2...>) { } } //cross of two packs, this could be same pack too
for constexpr (typename A : pack<int, long, char>) { } //usage without any
parameter pack and outside any template

And for `break` and `continue`. Only real problem there is `continue`
because `break` can be easy fix by adding one after `for`. Another is this
interaction should be well know for every one because is already same for
normal loops:
while(y)
{
  switch(x)
  {
    default: while(x)
    {
      --x;
      case 1: --x;
      case 5: --x; if (x == 7) break; //this is inner `while` break.
    }
    break; //break for quitting after inner `while`

    case 10: x += 10; continue; //this is outer `while` continue.

    for constexpr (int A : Cases...)
    {
      case 10 + A: func<A>(x);
      if (A & 1) continue; //`for constexpr` continue
      break; //`for constexpr` break
    }
    break; //break for quitting after `for`
  }
}

I think losing `continue` for outer loop is worth price paying for this
functionality.



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/24080b48-d084-4c5f-bb3f-fef677baee12%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, smi=
li...@googlemail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr">On Thursday, July 7, 2016 at 8:33:50 AM UTC+2, Sergey Vidyuk =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><br><div>At least, I&#39;d be helpful to have SOME guidance from =
the standardization body, whether they prefer such a simple solution or whe=
ther they&#39;d like more work done on &quot;for constexpr&quot;(e.g.).=C2=
=A0<br></div></div></blockquote></div></blockquote><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div>And, if=C2=A0block/statement expansion won&#=
39;t move forward (for now), maybe=C2=A0add a more specific expansion for s=
witch/case (something akin to the &quot;first syntax idea&quot; from my fir=
st mail)?</div></div></blockquote></div></blockquote><div><br>some info on =
for constexpr discussed here:=20
<a href=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/=
std-proposals/2hdpLnXJKkQ" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgrou=
ps#!topic/std-proposals/2hdpLnXJKkQ&#39;;return true;" onclick=3D"this.href=
=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std=
-proposals/2hdpLnXJKkQ&#39;;return true;">https://groups.google.com/a/<wbr>=
isocpp.org/forum/?fromgroups#!<wbr>topic/std-proposals/<wbr>2hdpLnXJKkQ</a>
 Right now I&#39;m playing with gcc code (using my free time so progress is=
=20
not rapid enough). I want to have implementation I can play with and=20
share=20
with other people on this list and then start to work on proposal paper.<br=
><br></div></blockquote><div><div><br></div><div>What I don&#39;t like with=
 for constexpr is that it does not work so well with switch/case, because i=
t changes the destinations of continue/break. Also IMHO the syntax is quite=
 verbose.</div><div>Some kind of inplace - template/type destructuring woul=
d be nice, but you quickly get to the point of wanting the full matching po=
wer of partial template specialization. So that would certainly be too much=
 complexity.</div><div><br></div><div>Also note that some of the for conste=
xpr can already be achieved by fold-expressions. Except for goto/return, th=
at is:<br><br></div><div style=3D"border:1px solid rgb(187,187,187);word-wr=
ap:break-word;background-color:rgb(250,250,250)"><code><div><font color=3D"=
#000000"><span style=3D"color:#008">template</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008"=
>typename</span><span style=3D"color:#000"> T</span><span style=3D"color:#6=
60">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">struct</span><span style=3D"color:#000"> type_c </span><span style=3D"col=
or:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">typedef</span><span style=3D"color:#000"> T type</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">};</span><span style=3D"color:#000"><br></span></font><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">template</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#660">...</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#606">Ts</span><span style=
=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">// ...</span><span style=3D"color:#000"><br>=C2=A0 </span><=
span style=3D"color:#660">([&amp;](</span><span style=3D"color:#008">auto</=
span><span style=3D"color:#000"> t</span><span style=3D"color:#660">){</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"=
color:#008">using</span><span style=3D"color:#000"> T</span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#008">typename</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">decltype</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">t</span><span style=3D=
"color:#660">)::</span><span style=3D"color:#000">type</span><span style=3D=
"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#800">//... instead of &quot;continue;&quot; -&gt;=
 &quot;return true;&quot;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:#800">//... instead of &quot;break;&q=
uot; -&gt; &quot;return false;&quot;</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">return</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">true</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"=
color:#800">// must be inserted at the end</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0</span><span style=3D"color:#660">}(</span><span style=3D=
"color:#000">type_c</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#606">Ts</span><span style=3D"color:#660">&gt;())</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">&amp;&amp;</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">...</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"><br></span></div></code></div><div><br></div></div>A simila=
r transform is possible for non-type parameter packs.<br><br>=C2=A0 Tobias<=
/div></blockquote><div>Yes, `for constexpr` is far more verbose but this gi=
ve us lot more control over that happens. Dots work great when you want exp=
and one parameter pack but if is more of them or you want start do some com=
plex thing this will start be problematic.<br>Image you want use Cartesian =
product of two parameters pack. Without introducing completely new syntax y=
ou can&#39;t handle it. Of corse `for` have limitation too, but is lot of e=
asier remove it.<br>Only thing that `for constexpr` need to handle nearly a=
ll possible use cases is allow it to extract template parameters from concr=
ete templates (it would need have parameters like `template&lt;typename... =
T&gt;` or `template&lt;auto... A&gt;`):<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 clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #800;=
" class=3D"styled-by-prettify">// we have two packs, T1 and T2</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</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">...&gt;</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> pack</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">for</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> A </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> pack</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">T1</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">...,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> T2</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">...&gt;)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//pack merge</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">for</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">constexpr</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: #008;" class=3D"styled-by-pr=
ettify">typename</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> A </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> zip</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">pack</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">T1</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">...&gt;,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> pack</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">T2</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">...&gt;&gt;::</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">type</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//zip two parameters pack, `type` is `pack&lt;std::=
pair&lt;T1, T2&gt;...&gt;`</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">for</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">conste=
xpr</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> A </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> pack</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">T1</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...&gt;)</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: #008;" class=3D"styled-by-prettify">for</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> B </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> pack</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T2<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">...&gt;)</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </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: #800;" class=3D"styled-by-prettify">/=
/cross of two packs, this could be same pack too</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">for</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">constexpr</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">typ=
ename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> pack</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">long</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">char</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </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: #660;=
" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//usage without any parameter pack and outside any template<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
</div></code></div><br>And for `break` and `continue`. Only real problem th=
ere is `continue` because `break` can be easy fix by adding one after `for`=
.. Another is this interaction should be well know for every one because is =
already same for normal loops:<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: #008;" class=
=3D"styled-by-prettify">while</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">y</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">switch</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">x</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">default</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">while</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">x</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">--</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">case</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">1</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-prettif=
y">x</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>case</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">5</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: #6=
60;" class=3D"styled-by-prettify">--</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">x</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">i=
f</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">x </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" cl=
ass=3D"styled-by-prettify">7</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
break</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">//this is inner `while`=
 break.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">break</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">//break for quittin=
g after inner `while`</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">case</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">10</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> x </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">10</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">continue</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>//this is outer `while` continue.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">for</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">constexpr</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: #008;" class=3D"styled-by-prettify"=
>int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A </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: #606;" class=3D"styled-by-prettify">Cases</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">...)</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">case</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066=
;" class=3D"styled-by-prettify">10</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">+</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> func</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">A</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">x</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">if</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"style=
d-by-prettify">A </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">continue</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D=
"styled-by-prettify">//`for constexpr` continue</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">break</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: #800;" =
class=3D"styled-by-prettify">//`for constexpr` break</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">break</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: #800;" cla=
ss=3D"styled-by-prettify">//break for quitting after `for`</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </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></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span></div></code></div><br>I think lo=
sing `continue` for outer loop is worth price paying for this functionality=
..<br><br><br><br></div></div>

<p></p>

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

------=_Part_5858_1734611478.1467901744917--

------=_Part_5857_813396084.1467901744915--

.


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 7 Jul 2016 09:34:46 -0700 (PDT)
Raw View
------=_Part_4468_1502830075.1467909286980
Content-Type: multipart/alternative;
 boundary="----=_Part_4469_1574063416.1467909286980"

------=_Part_4469_1574063416.1467909286980
Content-Type: text/plain; charset=UTF-8

On Thursday, July 7, 2016 at 4:29:05 PM UTC+2, inkwizyt...@gmail.com wrote:
>
> On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, smili...@googlemail.com
> wrote:
>>
>> Yes, `for constexpr` is far more verbose but this give us lot more
>> control over that happens. Dots work great when you want expand one
>> parameter pack but if is more of them or you want start do some complex
>> thing this will start be problematic.
>>
> Image you want use Cartesian product of two parameters pack. Without
> introducing completely new syntax you can't handle it.
>

You can implement product<pack<T1...>,pack<T2...>>::type as a library
solution just like zip<..>. The only difference is that, for
Us=pair<T1,T2>... you might want to add "using A = Us::first...;" and
"using B = Us::second...;" for your convenience.


> Of corse `for` have limitation too, but is lot of easier remove it.
> Only thing that `for constexpr` need to handle nearly all possible use
> cases is allow it to extract template parameters from concrete templates
> (it would need have parameters like `template<typename... T>` or
> `template<auto... A>`):
> // we have two packs, T1 and T2
> template<typename...> pack{};
>
> for constexpr (typename A : pack<T1..., T2...>) { } //pack merge
> for constexpr (typename A : typename zip<pack<T1...>, pack<T2...>>::type)
> { } //zip two parameters pack, `type` is `pack<std::pair<T1, T2>...>`
> for constexpr (typename A : pack<T1...>) { for constexpr (typename B :
> pack<T2...>) { } } //cross of two packs, this could be same pack too
> for constexpr (typename A : pack<int, long, char>) { } //usage without
> any parameter pack and outside any template
>
> And for `break` and `continue`. Only real problem there is `continue`
> because `break` can be easy fix by adding one after `for`. Another is this
> interaction should be well know for every one because is already same for
> normal loops: [...]
>

The for constexpr proposal meshes two things together that don't have to:
One half is the semantic of "for", esp. wrt. to the creation of a
break/continue-scope. The other half is the "inline"-introduction of a new
parameter pack (i.e. without another indirection like function call /
template class).

The first half is IMO only weakly motivated; when you think of it, even the
name "for constexpr" is not exactly fitting, because you're (most
importantly) dealing with *types*, not constexpr
*values.*
The second half can be dealt with without touching break/continue - or even
forcing an expansion. Think about:

  using... Us = pack<int,char,long>;
  // ...
  { doSomething<Us> }...
  // ...

That's just a simple example, but the same thing works the same with
product, zip, and all the stuff from above (you can add "using A =
Ts::first;" as you like).

The real questions are: How will "using..." (or "for constexpr") know how
to "iterate the pack", i.e. find the variadic part?
When we look at how range-for was specified, we can see that it does not
"bless" a certain "range"-type, but uses whatever iterator begin() / end()
would return. So we're now talking about "meta"-iterators over types, like
Boost MPL - or Fusion - or Hana - or ... has. It's not like the *one true *solution
in this space has already been around long enough just waiting to get
standardized.

Anyway, I don't think these considerations should hold us back from adding
a *simple *statment/block-expansion facility to the language that already
solves 95% of the most common use-cases.

  Tobias



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9d82f1b6-b8cb-4b23-98de-329a0889d6b6%40isocpp.org.

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

<div dir=3D"ltr">On Thursday, July 7, 2016 at 4:29:05 PM UTC+2, inkwizyt...=
@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, <a>smili...@googlemail.c=
om</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Yes, =
`for constexpr` is far more verbose but this give us lot more control over =
that happens. Dots work great when you want expand one parameter pack but i=
f is more of them or you want start do some complex thing this will start b=
e problematic.<br></div></blockquote><div>Image you want use Cartesian prod=
uct of two parameters pack. Without introducing completely new syntax you c=
an&#39;t handle it.</div></div></blockquote><div><br></div><div>You can imp=
lement product&lt;pack&lt;T1...&gt;,pack&lt;T2...&gt;&gt;::type as a librar=
y solution just like zip&lt;..&gt;. The only difference is that, for Us=3Dp=
air&lt;T1,T2&gt;... you might want to add &quot;using A =3D Us::first...;&q=
uot; and &quot;using B =3D Us::second...;&quot; for your convenience.</div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div> Of corse `for` have limitation too, but is lot of easier remove i=
t.<br>Only thing that `for constexpr` need to handle nearly all possible us=
e cases is allow it to extract template parameters from concrete templates =
(it would need have parameters like `template&lt;typename... T&gt;` or `tem=
plate&lt;auto... A&gt;`):<br><div style=3D"background-color:rgb(250,250,250=
);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wr=
ap:break-word"><code><div><span style=3D"color:#800">// we have two packs, =
T1 and T2</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#008">template</span><span style=3D"color:#660">&lt;</span><span style=3D"c=
olor:#008">typename</span><span style=3D"color:#660">...&gt;</span><span st=
yle=3D"color:#000"> pack</span><span style=3D"color:#660">{};</span><span s=
tyle=3D"color:#000"><br><br></span><span style=3D"color:#008">for</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">constexpr</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span=
 style=3D"color:#008">typename</span><span style=3D"color:#000"> A </span><=
span style=3D"color:#660">:</span><span style=3D"color:#000"> pack</span><s=
pan style=3D"color:#660">&lt;</span><span style=3D"color:#000">T1</span><sp=
an style=3D"color:#660">...,</span><span style=3D"color:#000"> T2</span><sp=
an style=3D"color:#660">...&gt;)</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">//pack merge</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">for</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">typename</span>=
<span style=3D"color:#000"> A </span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">typename</span><=
span style=3D"color:#000"> zip</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#000">pack</span><span style=3D"color:#660">&lt;</span=
><span style=3D"color:#000">T1</span><span style=3D"color:#660">...&gt;,</s=
pan><span style=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">T2</span><span style=3D"color:#660">...&gt=
;&gt;::</span><span style=3D"color:#000">type</span><span style=3D"color:#6=
60">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#800">//zip two p=
arameters pack, `type` is `pack&lt;std::pair&lt;T1, T2&gt;...&gt;`</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#008">for</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">constexpr</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">typename</span><span style=3D"color:#000"> A </span>=
<span style=3D"color:#660">:</span><span style=3D"color:#000"> pack</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#000">T1</span><s=
pan style=3D"color:#660">...&gt;)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">for</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">(</span><span style=3D"color:#008">typename</span><sp=
an style=3D"color:#000"> B </span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;</span><spa=
n style=3D"color:#000">T2</span><span style=3D"color:#660">...&gt;)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#800">//cross of two packs, this co=
uld be same pack too</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#008">for</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">typename</span><span =
style=3D"color:#000"> A </span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;</span><span s=
tyle=3D"color:#008">int</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">long</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">char</span><span style=3D"color:#660">&gt;)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#800">//usage without any parameter pack an=
d outside any template</span><span style=3D"color:#000"><br></span></div></=
code></div><br>And for `break` and `continue`. Only real problem there is `=
continue` because `break` can be easy fix by adding one after `for`. Anothe=
r is this interaction should be well know for every one because is already =
same for normal loops: [...]</div></div></blockquote><div>=C2=A0</div><div>=
The for constexpr proposal meshes two things together that don&#39;t have t=
o: One half is the semantic of &quot;for&quot;, esp. wrt. to the creation o=
f a break/continue-scope. The other half is the &quot;inline&quot;-introduc=
tion of a new parameter pack (i.e. without another indirection like functio=
n call / template class).=C2=A0</div><div><br>The first half is IMO only we=
akly motivated; when you think of it, even the name &quot;for constexpr&quo=
t; is not exactly fitting, because you&#39;re (most importantly) dealing wi=
th <i>types</i>, not constexpr <i>values.<br></i><br>The second half can be=
 dealt with without touching break/continue - or even forcing an expansion.=
 Think about:<br><br></div><div class=3D"prettyprint" style=3D"border: 1px =
solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250,=
 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">using</span><span style=
=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: #606;=
" class=3D"styled-by-prettify">Us</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> pack</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">char</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">long</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&gt;;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #800;=
" class=3D"styled-by-prettify">// ...</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> doSomething</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Us</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}...</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </s=
pan><span style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div>=
</code></div><div><br></div><div>That&#39;s just a simple example, but the =
same thing works the same with product, zip, and all the stuff from above (=
you can add &quot;using A =3D Ts::first;&quot; as you like).<br><br>The rea=
l questions are: How will &quot;using...&quot; (or &quot;for constexpr&quot=
;) know how to &quot;iterate the pack&quot;, i.e. find the variadic part?=
=C2=A0<br>When we look at how range-for was specified, we can see that it d=
oes not &quot;bless&quot; a certain &quot;range&quot;-type, but uses whatev=
er iterator begin() / end() would return. So we&#39;re now talking about &q=
uot;meta&quot;-iterators over types, like Boost MPL - or Fusion - or Hana -=
 or ... has. It&#39;s not like the <i>one true </i>solution in this space h=
as already been around long enough just waiting to get standardized.<br><br=
>Anyway, I don&#39;t think these considerations should hold us back from ad=
ding a <i>simple </i>statment/block-expansion facility to the language that=
 already solves 95% of the most common use-cases.</div><div><br></div><div>=
=C2=A0 Tobias<br><br></div><div>=C2=A0</div></div>

<p></p>

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

------=_Part_4469_1574063416.1467909286980--

------=_Part_4468_1502830075.1467909286980--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 7 Jul 2016 09:46:36 -0700 (PDT)
Raw View
------=_Part_5653_1945814723.1467909996436
Content-Type: multipart/alternative;
 boundary="----=_Part_5654_475247157.1467909996436"

------=_Part_5654_475247157.1467909996436
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thursday, July 7, 2016 at 9:05:30 AM UTC-4, Micha=C5=82 Dominiak wrote:
>
> On Thu, Jul 7, 2016 at 2:53 PM smilingthax via ISO C++ Standard - Future=
=20
> Proposals <std-pr...@isocpp.org <javascript:>> wrote:
>
>> On Wednesday, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bolas wrote:
>>>
>>> Things don't get standardized because someone posts a suggestion in a=
=20
>>> mailing list. Things get standardized because someone puts work and eff=
ort=20
>>> into it, pushing it forward at actual standards meetings.
>>>
>>
>> Sure. But not all of us are in a position to participate in standards=20
>> meetings.
>>
> =20
> You don't need to participate in a meeting yourself; all you'd need to do=
=20
> is 1) write a paper (and yes, this is considered effort, and if you reall=
y=20
> want something, you should put that effort into it), and 2) find somebody=
=20
> to champion the proposal. You are saying there's a lot of people wanting=
=20
> this (frankly I agree, myself included), which should mean that finding a=
=20
> champion for this shouldn't be very hard.
>
> But the very first step in finding a champion is actually writing a paper=
,=20
> so that people may look at what is the actual thing you are proposing,=20
> what's the rationale, what problems it solves, ..., and possibly get=20
> interested in it.
>

I'm curious: how many proposals have actually gotten through the committee=
=20
with *just* a champion?=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/bfd3466f-2930-4859-ba25-9a974f35dd0e%40isocpp.or=
g.

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

<div dir=3D"ltr">On Thursday, July 7, 2016 at 9:05:30 AM UTC-4, Micha=C5=82=
 Dominiak wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div class=3D"gmail_quote"><div dir=3D"ltr">On Thu, Jul 7, 2016 at 2:53 =
PM smilingthax via ISO C++ Standard - Future Proposals &lt;<a href=3D"javas=
cript:" target=3D"_blank" gdf-obfuscated-mailto=3D"Biwr8TseCQAJ" rel=3D"nof=
ollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" oncli=
ck=3D"this.href=3D&#39;javascript:&#39;;return true;">std-pr...@isocpp.org<=
/a>&gt; wrote:<br></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">On =
Wednesday, July 6, 2016 at 3:25:22 AM UTC+2, Nicol Bolas wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Things don&#39;t get stan=
dardized because someone posts a suggestion in a mailing list. Things get s=
tandardized because someone puts work and effort into it, pushing it forwar=
d at actual standards meetings.<br></div></div></blockquote><div><br></div>=
</div><div dir=3D"ltr"><div>Sure. But not all of us are in a position to pa=
rticipate in standards meetings.</div></div></blockquote><div>=C2=A0</div><=
div>You don&#39;t need to participate in a meeting yourself; all you&#39;d =
need to do is 1) write a paper (and yes, this is considered effort, and if =
you really want something, you should put that effort into it), and 2) find=
 somebody to champion the proposal. You are saying there&#39;s a lot of peo=
ple wanting this (frankly I agree, myself included), which should mean that=
 finding a champion for this shouldn&#39;t be very hard.</div><div><br></di=
v><div>But the very first step in finding a champion is actually writing a =
paper, so that people may look at what is the actual thing you are proposin=
g, what&#39;s the rationale, what problems it solves, ..., and possibly get=
 interested in it.</div></div></div></blockquote><div><br>I&#39;m curious: =
how many proposals have actually gotten through the committee with <i>just<=
/i> a champion? <br></div></div>

<p></p>

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

------=_Part_5654_475247157.1467909996436--

------=_Part_5653_1945814723.1467909996436--

.


Author: inkwizytoryankes@gmail.com
Date: Thu, 7 Jul 2016 11:58:58 -0700 (PDT)
Raw View
------=_Part_849_1289121215.1467917939011
Content-Type: multipart/alternative;
 boundary="----=_Part_850_348445561.1467917939012"

------=_Part_850_348445561.1467917939012
Content-Type: text/plain; charset=UTF-8



On Thursday, July 7, 2016 at 6:34:47 PM UTC+2, smili...@googlemail.com
wrote:
>
> On Thursday, July 7, 2016 at 4:29:05 PM UTC+2, inkwizyt...@gmail.com
> wrote:
>>
>> On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, smili...@googlemail.com
>> wrote:
>>>
>>> Yes, `for constexpr` is far more verbose but this give us lot more
>>> control over that happens. Dots work great when you want expand one
>>> parameter pack but if is more of them or you want start do some complex
>>> thing this will start be problematic.
>>>
>> Image you want use Cartesian product of two parameters pack. Without
>> introducing completely new syntax you can't handle it.
>>
>
> You can implement product<pack<T1...>,pack<T2...>>::type as a library
> solution just like zip<..>. The only difference is that, for
> Us=pair<T1,T2>... you might want to add "using A = Us::first...;" and
> "using B = Us::second...;" for your convenience.
>
>
>> Of corse `for` have limitation too, but is lot of easier remove it.
>> Only thing that `for constexpr` need to handle nearly all possible use
>> cases is allow it to extract template parameters from concrete templates
>> (it would need have parameters like `template<typename... T>` or
>> `template<auto... A>`):
>> // we have two packs, T1 and T2
>> template<typename...> pack{};
>>
>> for constexpr (typename A : pack<T1..., T2...>) { } //pack merge
>> for constexpr (typename A : typename zip<pack<T1...>, pack<T2...>>::type)
>> { } //zip two parameters pack, `type` is `pack<std::pair<T1, T2>...>`
>> for constexpr (typename A : pack<T1...>) { for constexpr (typename B :
>> pack<T2...>) { } } //cross of two packs, this could be same pack too
>> for constexpr (typename A : pack<int, long, char>) { } //usage without
>> any parameter pack and outside any template
>>
>> And for `break` and `continue`. Only real problem there is `continue`
>> because `break` can be easy fix by adding one after `for`. Another is this
>> interaction should be well know for every one because is already same for
>> normal loops: [...]
>>
>
> The for constexpr proposal meshes two things together that don't have to:
> One half is the semantic of "for", esp. wrt. to the creation of a
> break/continue-scope. The other half is the "inline"-introduction of a new
> parameter pack (i.e. without another indirection like function call /
> template class).
>
>
Yes, I try sneak two proposal at once, but this approach have one bug
advantage. Using only one sentence in standard I can effective made
"inline"-introduction of parameters packs. Trying doing this explicitly
will probably need lot of more effort to write and getting it pass through
committee.


> The first half is IMO only weakly motivated; when you think of it, even
> the name "for constexpr" is not exactly fitting, because you're (most
> importantly) dealing with *types*, not constexpr
> *values.*
>
Its use syntax similar to iterating over container, in this case container
is pack and object in that containers are types. I could say this is more
abstract version of `for`.


> The second half can be dealt with without touching break/continue - or
> even forcing an expansion. Think about:
>
>   using... Us = pack<int,char,long>;
>   // ...
>   { doSomething<Us> }...
>   // ...
>
> That's just a simple example, but the same thing works the same with
> product, zip, and all the stuff from above (you can add "using A =
> Ts::first;" as you like).
>
>
There was already some discussion about stand alone parameter packs. You
will need limit where they can be defined otherwise problems will arise:
{ someType<Us>::thisIsPackToo; }...
You need describe how handle this situation.



> The real questions are: How will "using..." (or "for constexpr") know how
> to "iterate the pack", i.e. find the variadic part?
> When we look at how range-for was specified, we can see that it does not
> "bless" a certain "range"-type, but uses whatever iterator begin() / end()
> would return. So we're now talking about "meta"-iterators over types, like
> Boost MPL - or Fusion - or Hana - or ... has. It's not like the *one true
> *solution in this space has already been around long enough just waiting
> to get standardized.
>
>
At least for that I propose its simple. Extraction of pack can only be done
for concrete template that have only variadic pack. And then we loop for
each element of this pack in order as it appear in pack.
This will ignore lot of possible template parameters (like mixing types
with values) but in most cases you can manually extract pack using template
meta programing:

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

template<typename T>
struct Extract
{
};
template<template<typename... > typename A, typename... T>
struct Extract<A<T...>>
{
  using type = pack<T...>;
};

template<typename A, typename B>
struct Z
{
};

using Y = typename Extract<Z<int, double>>::type; //pack<int, double>

Even if what you want isn't pack like class members mapped by hana you
probably always can transform it using hana functionality to some pack that
will work with `for`.



> Anyway, I don't think these considerations should hold us back from adding
> a *simple *statment/block-expansion facility to the language that already
> solves 95% of the most common use-cases.
>
>   Tobias
>
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1be58128-061c-4b81-b783-135e9b5127fc%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Thursday, July 7, 2016 at 6:34:47 PM UTC+2, smi=
li...@googlemail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr">On Thursday, July 7, 2016 at 4:29:05 PM UTC+2, <a>inkwizyt...=
@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r">On Thursday, July 7, 2016 at 3:08:34 PM UTC+2, <a>smili...@googlemail.co=
m</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Yes, `=
for constexpr` is far more verbose but this give us lot more control over t=
hat happens. Dots work great when you want expand one parameter pack but if=
 is more of them or you want start do some complex thing this will start be=
 problematic.<br></div></blockquote><div>Image you want use Cartesian produ=
ct of two parameters pack. Without introducing completely new syntax you ca=
n&#39;t handle it.</div></div></blockquote><div><br></div><div>You can impl=
ement product&lt;pack&lt;T1...&gt;,pack&lt;T2...<wbr>&gt;&gt;::type as a li=
brary solution just like zip&lt;..&gt;. The only difference is that, for Us=
=3Dpair&lt;T1,T2&gt;... you might want to add &quot;using A =3D Us::first..=
..;&quot; and &quot;using B =3D Us::second...;&quot; for your convenience.</=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div> Of corse `for` have limitation too, but is lot of easier remove it=
..<br>Only thing that `for constexpr` need to handle nearly all possible use=
 cases is allow it to extract template parameters from concrete templates (=
it would need have parameters like `template&lt;typename... T&gt;` or `temp=
late&lt;auto... A&gt;`):<br><div style=3D"background-color:rgb(250,250,250)=
;border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wra=
p:break-word"><code><div><span style=3D"color:#800">// we have two packs, T=
1 and T2</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
008">template</span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#008">typename</span><span style=3D"color:#660">...&gt;</span><span sty=
le=3D"color:#000"> pack</span><span style=3D"color:#660">{};</span><span st=
yle=3D"color:#000"><br><br></span><span style=3D"color:#008">for</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">constexpr</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span =
style=3D"color:#008">typename</span><span style=3D"color:#000"> A </span><s=
pan style=3D"color:#660">:</span><span style=3D"color:#000"> pack</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#000">T1</span><spa=
n style=3D"color:#660">...,</span><span style=3D"color:#000"> T2</span><spa=
n style=3D"color:#660">...&gt;)</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">}</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">//pack merge</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">for</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">typename</span>=
<span style=3D"color:#000"> A </span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">typename</span><=
span style=3D"color:#000"> zip</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#000">pack</span><span style=3D"color:#660">&lt;</span=
><span style=3D"color:#000">T1</span><span style=3D"color:#660">...&gt;,</s=
pan><span style=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">T2</span><span style=3D"color:#660">...&gt=
;&gt;::</span><span style=3D"color:#000">type</span><span style=3D"color:#6=
60">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#800">//zip two p=
arameters pack, `type` is `pack&lt;std::pair&lt;T1, T2&gt;...&gt;`</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#008">for</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">constexpr</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">typename</span><span style=3D"color:#000"> A </span>=
<span style=3D"color:#660">:</span><span style=3D"color:#000"> pack</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#000">T1</span><s=
pan style=3D"color:#660">...&gt;)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">for</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">(</span><span style=3D"color:#008">typename</span><sp=
an style=3D"color:#000"> B </span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;</span><spa=
n style=3D"color:#000">T2</span><span style=3D"color:#660">...&gt;)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#800">//cross of two packs, this co=
uld be same pack too</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#008">for</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">typename</span><span =
style=3D"color:#000"> A </span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;</span><span s=
tyle=3D"color:#008">int</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">long</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">char</span><span style=3D"color:#660">&gt;)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#800">//usage without any parameter pack an=
d outside any template</span><span style=3D"color:#000"><br></span></div></=
code></div><br>And for `break` and `continue`. Only real problem there is `=
continue` because `break` can be easy fix by adding one after `for`. Anothe=
r is this interaction should be well know for every one because is already =
same for normal loops: [...]</div></div></blockquote><div>=C2=A0</div><div>=
The for constexpr proposal meshes two things together that don&#39;t have t=
o: One half is the semantic of &quot;for&quot;, esp. wrt. to the creation o=
f a break/continue-scope. The other half is the &quot;inline&quot;-introduc=
tion of a new parameter pack (i.e. without another indirection like functio=
n call / template class).=C2=A0</div><div><br></div></div></blockquote><div=
><br>Yes, I try sneak two proposal at once, but this approach have one bug =
advantage. Using only one sentence in standard I can effective made &quot;i=
nline&quot;-introduction of parameters packs. Trying doing this explicitly =
will probably need lot of more effort to write and getting it pass through =
committee.<br>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr"><div>The first half is IMO only weakly motivated; when you=
 think of it, even the name &quot;for constexpr&quot; is not exactly fittin=
g, because you&#39;re (most importantly) dealing with <i>types</i>, not con=
stexpr <i>values.<br></i><br></div></div></blockquote><div>Its use syntax s=
imilar to iterating over container, in this case container is pack and obje=
ct in that containers are types. I could say this is more abstract version =
of `for`.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><div>The second half can be dealt with without touching break/c=
ontinue - or even forcing an expansion. Think about:<br><br></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:#000">=C2=A0 </span><sp=
an style=3D"color:#008">using</span><span style=3D"color:#660">...</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#606">Us</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> pack</span><span style=3D"color:#660">&lt;</span><span s=
tyle=3D"color:#008">int</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#008">char</span><span style=3D"color:#660">,</span><span style=
=3D"color:#008">long</span><span style=3D"color:#660">&gt;;</span><span sty=
le=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">// ...</span=
><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> doSomething</span><span style=3D"color:#6=
60">&lt;</span><span style=3D"color:#606">Us</span><span style=3D"color:#66=
0">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>}...</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"col=
or:#800">// ...</span><span style=3D"color:#000"><br></span></div></code></=
div><div><br></div><div>That&#39;s just a simple example, but the same thin=
g works the same with product, zip, and all the stuff from above (you can a=
dd &quot;using A =3D Ts::first;&quot; as you like).<br><br></div></div></bl=
ockquote><div><br>There was already some discussion about stand alone param=
eter packs. You will need limit where they can be defined otherwise problem=
s will arise:<br><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> som=
eType</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Us</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&gt;::</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">thisIsPackToo</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">}...</span></div></code></div>You nee=
d describe how handle this situation.<br><br>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>The real questions are: H=
ow will &quot;using...&quot; (or &quot;for constexpr&quot;) know how to &qu=
ot;iterate the pack&quot;, i.e. find the variadic part?=C2=A0<br>When we lo=
ok at how range-for was specified, we can see that it does not &quot;bless&=
quot; a certain &quot;range&quot;-type, but uses whatever iterator begin() =
/ end() would return. So we&#39;re now talking about &quot;meta&quot;-itera=
tors over types, like Boost MPL - or Fusion - or Hana - or ... has. It&#39;=
s not like the <i>one true </i>solution in this space has already been arou=
nd long enough just waiting to get standardized.<br><br></div></div></block=
quote><div><br>At least for that I propose its simple. Extraction of pack c=
an only be done for concrete template that have only variadic pack. And the=
n we loop for each element of this pack in order as it appear in pack.<br>T=
his will ignore lot of possible template parameters (like mixing types with=
 values) but in most cases you can manually extract pack using template met=
a programing:<br><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">t=
emplate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt=
;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">...&gt;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> pack<br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">typename</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">stru=
ct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Extract</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></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">template</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">template</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">typename</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> A</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">typename</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Extract</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">A</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">...&gt;&gt;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">using</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> type </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> pack=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">...&gt;;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></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">&lt;</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> A</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ty=
pename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> B</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> Z<br></span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=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"st=
yled-by-prettify">using</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> Y </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Extract</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">Z</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">double</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&gt;&gt;::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">type</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">//pack&lt;int, double=
&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><b=
r></span></div></code></div>Even if what you want isn&#39;t pack like class=
 members mapped by hana you probably always can transform it using hana fun=
ctionality to some pack that will work with `for`.<br><br>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Anyway, I don=
&#39;t think these considerations should hold us back from adding a <i>simp=
le </i>statment/block-expansion facility to the language that already solve=
s 95% of the most common use-cases.</div><div><br></div><div>=C2=A0 Tobias<=
br><br></div><div>=C2=A0</div></div></blockquote></div>

<p></p>

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

------=_Part_850_348445561.1467917939012--

------=_Part_849_1289121215.1467917939011--

.


Author: Sergey Vidyuk <sir.vestnik@gmail.com>
Date: Fri, 8 Jul 2016 00:40:28 -0700 (PDT)
Raw View
------=_Part_21_2009627525.1467963628531
Content-Type: multipart/alternative;
 boundary="----=_Part_22_957913456.1467963628532"

------=_Part_22_957913456.1467963628532
Content-Type: text/plain; charset=UTF-8


>
> The real questions are: How will "using..." (or "for constexpr") know how
> to "iterate the pack", i.e. find the variadic part?
> When we look at how range-for was specified, we can see that it does not
> "bless" a certain "range"-type, but uses whatever iterator begin() / end()
> would return. So we're now talking about "meta"-iterators over types, like
> Boost MPL - or Fusion - or Hana - or ... has. It's not like the *one true
> *solution in this space has already been around long enough just waiting
> to get standardized.
>

The reason why runtime range for is specified in terms of begin/end
function and iterators is nececsity to work with user provided collection
types. In case of compile time for constexpr we have only one builtin
collection type: variadic pack and it's easy to specify how it should be
iterated. And I'm strongly against of introducing user types whith compile
time collection semantic. It adds too much complexity to the C++
metaprogramming system which is overcomplicated already. We don't need to
lazy iteration over bytes received from the socket transformet into parsed
messages accessible as iterable range at compile time.

I feel that the discussion here can be much more usefull if we start to
compare both appreaches "for constexpr" and "block expansion" for
applicability in desired usecases.

   - Both aproaches solve the task to instantiate block of code for each
   member of variadic pack with straight forward and easy to read syntax. My
   personal opinion here is: we already have range for syntax for runtime
   iteration over collection and all of the developers are familiar with it.
   Block expansion syntax is good but it new syntax and from my point of vew
   reusing of existing syntax is better since all of the C++ developers who
   are not familiar with template metaprogramming (actually the biggest part
   of C++ users) will understand the code without any problems. But it's not
   too hard for average programmer to guess block expansion syntax anyway.
   - break and continue semantic of for-loop has poor motivation but it can
   be implemented in block expansion as well (for constexpr version is easier
   to read but this can only be used as argumemt if we will find strong
   motivation for the feature):
   template<typename... T>
   void foo_block_expanded(T... t) {
       {
           if constexpr (index_of_v<T, T...> < index_of_v<std::nullptr_t,
   T...>) { // break on std::nullptr_t in the type list
               bar(t);
               if constexpr (should_not_skipp_v<T>) // contunue if type
   should be skipped
                   do_the_thing(t);
           }
       }...
   }


   - Iteration over type list outside of template code is not directly
   proposed in both approaches but widely discussed. I don't like the idea of
   grabbing template parameters since almost any template in stl, boost and
   many other libraries has additional parameters with default or deduceable
   values. The result of the following loop "for constexpr (typename T,
   std::map<int, std::string>)" might be surprasing. I like the way D handles
   this task and how easy it can be adopted in C++ but it have to be
   additional proposal of quite independent feature which is actually usable
   for bigger set of tasks. Both "for constexpr" and "block expansion" may be
   extended to have iteration over types in non-template code:
   template<typename... T>
   struct types {
    using list = T;
   };

   void foo1() {
       for constexpr (typename T: types<int, std::string>::list) {
           T val;
           std::cin >> val;
           std::cout << val << std::endl;
       }
   }

   void foo2() {
       using typelist = types<int, std::string>::list;
       {
           typelist val;
           std::cint >> val;
           std::cout << val << std::endl;
       }...
   }


   - Task to unpack more then one parameters pack. Trivial with for
   constexpr but how the following code should be compiled:

template<typename... L1>
struct A {
  template<typename... L2>
  void foo(L2... a) {
    {
      {
        bar<L1>(a);
      }...
    }...

    {
      baz<L2>(a);
    }...
  }
};
I assume that baz<L2>(a) expansion should be turned into baz<L2[0]>(a[0]);
.... baz<L2[N]>(a[N]); as it work in C++11 pack expansion rules. Looks like
the inner part of the bar-expansion should work in a diferent way. I
haven't found good way to solve this issue yet.

Sergey

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/038d5c35-3d49-4b50-8b61-cb0cca013dce%40isocpp.org.

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

<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>The real questions are: How will &quot;using...&quot; (or &quot;fo=
r constexpr&quot;) know how to &quot;iterate the pack&quot;, i.e. find the =
variadic part?=C2=A0<br>When we look at how range-for was specified, we can=
 see that it does not &quot;bless&quot; a certain &quot;range&quot;-type, b=
ut uses whatever iterator begin() / end() would return. So we&#39;re now ta=
lking about &quot;meta&quot;-iterators over types, like Boost MPL - or Fusi=
on - or Hana - or ... has. It&#39;s not like the <i>one true </i>solution i=
n this space has already been around long enough just waiting to get standa=
rdized.<br></div></div></blockquote><div><br>The reason why runtime range f=
or is specified in terms of begin/end function and iterators is nececsity t=
o work with user provided collection types. In case of compile time for con=
stexpr we have only one builtin collection type: variadic pack and it&#39;s=
 easy to specify how it should be iterated. And I&#39;m strongly against of=
 introducing user types whith compile time collection semantic. It adds too=
 much complexity to the C++ metaprogramming system which is overcomplicated=
 already. We don&#39;t need to lazy iteration over bytes received from the =
socket transformet into parsed messages accessible as iterable range at com=
pile time.<br><br>I feel that the discussion here can be much more usefull =
if we start to compare both appreaches &quot;for constexpr&quot; and &quot;=
block expansion&quot; for applicability in desired usecases.<br><ul><li>Bot=
h aproaches solve the task to instantiate block of code for each member of =
variadic pack with straight forward and easy to read syntax. My personal op=
inion here is: we already have range for syntax for runtime iteration over =
collection and all of the developers are familiar with it. Block expansion =
syntax is good but it new syntax and from my point of vew reusing of existi=
ng syntax is better since all of the C++ developers who are not familiar wi=
th template metaprogramming (actually the biggest part of C++ users) will u=
nderstand the code without any problems. But it&#39;s not too hard for aver=
age programmer to guess block expansion syntax anyway.</li><li>break and co=
ntinue semantic of for-loop has poor motivation but it can be implemented i=
n block expansion as well (for constexpr version is easier to read but this=
 can only be used as argumemt if we will find strong motivation for the fea=
ture):<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 2=
50); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1=
px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpr=
ettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">templa=
te</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</sp=
an><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"styled-by-prettify"> T</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">_block_expanded(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> t</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #000;" class=3D"styled-by-prettify"><co=
de class=3D"prettyprint"><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">constexpr=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"></span></c=
ode> (index_of_v&lt;T, T...&gt; &lt; </span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><code class=3D"prettyprint"><span style=3D"color=
: #000;" class=3D"styled-by-prettify">index_of_v&lt;std::nullptr_t, T...&gt=
;</span></code>) { // break on std::nullptr_t in the type list<br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 bar</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">t</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">constexpr</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">should_not_skipp_v</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&gt;)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 // contunue if type should be skipped<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 do_the_thing</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">t</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}...</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"></span><br></div></code></d=
iv></li></ul><ul><li>Iteration over type list outside of template code is n=
ot directly proposed in both approaches but widely discussed. I don&#39;t l=
ike the idea of grabbing template parameters since almost any template in s=
tl, boost and many other libraries has additional parameters with default o=
r deduceable values. The result of the following loop &quot;for constexpr (=
typename T, std::map&lt;int, std::string&gt;)&quot; might be surprasing. I =
like the way D handles this task and how easy it can be adopted in C++ but =
it have to be additional proposal of quite independent feature which is act=
ually usable for bigger set of tasks. Both &quot;for constexpr&quot; and &q=
uot;block expansion&quot; may be extended to have iteration over types in n=
on-template code:<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: #660;" class=3D"styled-by-p=
rettify">template&lt;typename... T&gt;<br>struct types {<br>=C2=A0using lis=
t =3D T;<br>};</span><br><br>void foo1() {<br>=C2=A0=C2=A0=C2=A0 for conste=
xpr (typename T: types&lt;<code class=3D"prettyprint">int, std::string</cod=
e>&gt;::list) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 T val;<br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cin &gt;&gt; val;<br>=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; val &lt;&lt; std::endl=
;<br>=C2=A0=C2=A0=C2=A0 }<br>}<br><br>void foo2() {<br>=C2=A0=C2=A0=C2=A0 u=
sing typelist =3D types&lt;int, std::string&gt;::list;<br>=C2=A0=C2=A0=C2=
=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 typelist val;<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cint &gt;&gt; val;<br>=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; val &lt;&lt; std::endl=
;<br>=C2=A0=C2=A0=C2=A0 }...<br>}<br></div></code></div></li></ul><ul><li>T=
ask to unpack more then one parameters pack. Trivial with for constexpr but=
 how the following code should be compiled:</li></ul><div class=3D"prettypr=
int" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, =
187, 187); border-style: solid; border-width: 1px; word-wrap: break-word; m=
argin-left: 40px;"><code class=3D"prettyprint"><div class=3D"subprettyprint=
"><span style=3D"color: #660;" class=3D"styled-by-prettify">template&lt;typ=
ename... L1&gt;<br>struct A {<br>=C2=A0 template&lt;typename... L2&gt;<br>=
=C2=A0 void foo(L2... a) {<br>=C2=A0=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bar&lt;L1&gt;(a);=
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }...<br>=C2=A0=C2=A0=C2=A0 }...<br><br>=
=C2=A0=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 baz&lt;L2&gt;(a);<br=
>=C2=A0=C2=A0=C2=A0 }...<br>=C2=A0 }<br>};</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"></span></div></code></div><div style=3D"mar=
gin-left: 40px;">I assume that baz&lt;L2&gt;(a) expansion should be turned =
into baz&lt;L2[0]&gt;(a[0]); ... baz&lt;L2[N]&gt;(a[N]); as it work in C++1=
1 pack expansion rules. Looks like the inner part of the bar-expansion shou=
ld work in a diferent way. I haven&#39;t found good way to solve this issue=
 yet.<br></div><br>Sergey<br></div></div>

<p></p>

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

------=_Part_22_957913456.1467963628532--

------=_Part_21_2009627525.1467963628531--

.


Author: "smilingthax via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 8 Jul 2016 03:21:35 -0700 (PDT)
Raw View
------=_Part_140_552459017.1467973295794
Content-Type: multipart/alternative;
 boundary="----=_Part_141_1875291675.1467973295795"

------=_Part_141_1875291675.1467973295795
Content-Type: text/plain; charset=UTF-8

On Friday, July 8, 2016 at 9:40:29 AM UTC+2, Sergey Vidyuk wrote:
>
> The real questions are: How will "using..." (or "for constexpr") know how
>> to "iterate the pack", i.e. find the variadic part?
>> When we look at how range-for was specified, we can see that it does not
>> "bless" a certain "range"-type, but uses whatever iterator begin() / end()
>> would return. So we're now talking about "meta"-iterators over types, like
>> Boost MPL - or Fusion - or Hana - or ... has. It's not like the *one
>> true *solution in this space has already been around long enough just
>> waiting to get standardized.
>>
>
> The reason why runtime range for is specified in terms of begin/end
> function and iterators is nececsity to work with user provided collection
> types. In case of compile time for constexpr we have only one builtin
> collection type: variadic pack and it's easy to specify how it should be
> iterated. And I'm strongly against of introducing user types whith compile
> time collection semantic. It adds too much complexity to the C++
> metaprogramming system which is overcomplicated already. We don't need to
> lazy iteration over bytes received from the socket transformet into parsed
> messages accessible as iterable range at compile time.
>

Well, lazy iteration over the cross-product of two packs would be nice...
Boost MPL does most things lazy IIRC.
I believe we will see more/new standardized facilities to work with
parameter packs, so that it is to early to commit to certain
design-decisions with for constexpr. E.g. assume we have a ...[] operator,
I could imagine something like this:
  for constexpr (int I=0; I<sizeof...(Ts); ++I) {
     foo<Ts...[I]>();
  }



> I feel that the discussion here can be much more usefull if we start to
> compare both appreaches "for constexpr" and "block expansion" for
> applicability in desired usecases. [...]
>

Thank you. For now I want to zoom in on your last point:

>
>    - Task to unpack more then one parameters pack. Trivial with for
>    constexpr but how the following code should be compiled:
>
> template<typename... L1>
> struct A {
>   template<typename... L2>
>   void foo(L2... a) {
>     {
>       {
>         bar<L1>(a);
>       }...
>     }...
>
>     {
>       baz<L2>(a);
>     }...
>   }
> };
> I assume that baz<L2>(a) expansion should be turned into baz<L2[0]>(a[0]);
> ... baz<L2[N]>(a[N]); as it work in C++11 pack expansion rules. Looks like
> the inner part of the bar-expansion should work in a diferent way. I
> haven't found good way to solve this issue yet.
>

So we somehow have to specify which of the packs should be expanded:

// either:
    {
      using X=L1; // (error: declaration contains unexpanded parameter pack)
      {
        bar<X>(a);
      }...
    }...
// or:
    {
      auto x=a;   // (error: initializer contains unexpanded parameter pack
'a')
      {
        bar<L1>(x);
      }...
    }...

The errors in parenthesis show the errors currently produced with the
clang-patch I posted earlier. The root cause is that I don't really know to
to handle unexpanded parameter packs in declarations: The clang AST
basically has three "root" types that are relevant: Stmt, Expr, Decl.
Expressions could handle unexpanded parameter packs since C++11. I had to
extend Statements to also handle them; but then there are Declarations...
These can "occur" in Expressions as DeclRefExpr, or as statement: DeclStmt.
I'm not sure how to handle the latter (big FIXME), because I think that we
will allow unexpanded parameters packs no just inside of VarDecls. OTOH I'm
not convinced that adding full support for unexpanded parameter packs to
Declarations, as I did for Statements, would be wise.

On a more abstract level, this means we have to look at and specify the
interaction of unexpanded parameter packs in Declarations. As I mentioned
earlier, it might be helpful to somewhat limit the "impact-range" of
unexpanded parameter packs e.g. in nested class function bodies. I'm not
too familiar with that part of the standard, though.
Your example was already helpful in showing me that "baz<L1>" (instead of
L2) already does work, i.e. the unexpanded parameter pack may come in from
outside the function body.
I'd really appreciate some help on that front.

  Tobias

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f4793b3c-ad91-4c1b-b104-11411c4a879f%40isocpp.org.

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

<div dir=3D"ltr">On Friday, July 8, 2016 at 9:40:29 AM UTC+2, Sergey Vidyuk=
 wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The real questions =
are: How will &quot;using...&quot; (or &quot;for constexpr&quot;) know how =
to &quot;iterate the pack&quot;, i.e. find the variadic part?=C2=A0<br>When=
 we look at how range-for was specified, we can see that it does not &quot;=
bless&quot; a certain &quot;range&quot;-type, but uses whatever iterator be=
gin() / end() would return. So we&#39;re now talking about &quot;meta&quot;=
-iterators over types, like Boost MPL - or Fusion - or Hana - or ... has. I=
t&#39;s not like the <i>one true </i>solution in this space has already bee=
n around long enough just waiting to get standardized.<br></div></div></blo=
ckquote><div><br>The reason why runtime range for is specified in terms of =
begin/end function and iterators is nececsity to work with user provided co=
llection types. In case of compile time for constexpr we have only one buil=
tin collection type: variadic pack and it&#39;s easy to specify how it shou=
ld be iterated. And I&#39;m strongly against of introducing user types whit=
h compile time collection semantic. It adds too much complexity to the C++ =
metaprogramming system which is overcomplicated already. We don&#39;t need =
to lazy iteration over bytes received from the socket transformet into pars=
ed messages accessible as iterable range at compile time.<br></div></div></=
blockquote><div><br></div><div>Well, lazy iteration over the cross-product =
of two packs would be nice... Boost MPL does most things lazy IIRC.<br>I be=
lieve we will see more/new standardized facilities to work with parameter p=
acks, so that it is to early to commit to certain design-decisions with for=
 constexpr. E.g. assume we have a ...[] operator, I could imagine something=
 like this:<br><div class=3D"prettyprint" style=3D"border: 1px solid rgb(18=
7, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">=C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">for</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">constexpr</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
I</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> I</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">...(</span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">++</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">I</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0foo</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">...[</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">I</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">]&gt;();</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span></div></code></div><br>=C2=A0<br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div>I feel that the discussion here=
 can be much more usefull if we start to compare both appreaches &quot;for =
constexpr&quot; and &quot;block expansion&quot; for applicability in desire=
d usecases. [...]<br></div></div></blockquote><div><br></div><div>Thank you=
.. For now I want to zoom in on your last point:=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><ul><li>Task to unpack m=
ore then one parameters pack. Trivial with for constexpr but how the follow=
ing code should be compiled:</li></ul><div style=3D"background-color:rgb(25=
0,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1p=
x;word-wrap:break-word;margin-left:40px"><code><div><span style=3D"color:#6=
60">template&lt;typename... L1&gt;<br>struct A {<br>=C2=A0 template&lt;type=
name... L2&gt;<br>=C2=A0 void foo(L2... a) {<br>=C2=A0=C2=A0=C2=A0 {<br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
 bar&lt;L1&gt;(a);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }...<br>=C2=A0=C2=A0=
=C2=A0 }...<br><br>=C2=A0=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 b=
az&lt;L2&gt;(a);<br>=C2=A0=C2=A0=C2=A0 }...<br>=C2=A0 }<br>};</span><span s=
tyle=3D"color:#660"></span></div></code></div><div style=3D"margin-left:40p=
x">I assume that baz&lt;L2&gt;(a) expansion should be turned into baz&lt;L2=
[0]&gt;(a[0]); ... baz&lt;L2[N]&gt;(a[N]); as it work in C++11 pack expansi=
on rules. Looks like the inner part of the bar-expansion should work in a d=
iferent way. I haven&#39;t found good way to solve this issue yet.</div></d=
iv></div></blockquote><div><br>So we somehow have to specify which of the p=
acks should be expanded:</div><div><br></div><div class=3D"prettyprint" sty=
le=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgrou=
nd-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #800;" class=3D"styled-by-prettify">// =
either:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">using</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> X</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">L1</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: #800;" class=3D"styled-by-prettify">// (error: declaration contains u=
nexpanded parameter pack)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bar</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">a</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}...</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">}...</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">// or:</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 </span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">// (error: initi=
alizer contains unexpanded parameter pack &#39;a&#39;)</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">L1</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}...</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">}...</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code><=
/div><div><br>The errors in parenthesis show the errors currently produced =
with the clang-patch I posted earlier. The root cause is that I don&#39;t r=
eally know to to handle unexpanded parameter packs in declarations: The cla=
ng AST basically has three &quot;root&quot; types that are relevant: Stmt, =
Expr, Decl. Expressions could handle unexpanded parameter packs since C++11=
.. I had to extend Statements to also handle them; but then there are Declar=
ations... These can &quot;occur&quot; in Expressions as DeclRefExpr, or as =
statement: DeclStmt. I&#39;m not sure how to handle the latter (big FIXME),=
 because I think that we will allow unexpanded parameters packs no just ins=
ide of VarDecls. OTOH I&#39;m not convinced that adding full support for un=
expanded parameter packs to Declarations, as I did for Statements, would be=
 wise.=C2=A0<br><br>On a more abstract level, this means we have to look at=
 and specify the interaction of unexpanded parameter packs in Declarations.=
 As I mentioned earlier, it might be helpful to somewhat limit the &quot;im=
pact-range&quot; of unexpanded parameter packs e.g. in nested class functio=
n bodies. I&#39;m not too familiar with that part of the standard, though.=
=C2=A0<br>Your example was already helpful in showing me that &quot;baz&lt;=
L1&gt;&quot; (instead of L2) already does work, i.e. the unexpanded paramet=
er pack may come in from outside the function body.<br>I&#39;d really appre=
ciate some help on that front.<br><br>=C2=A0 Tobias<br><br></div></div>

<p></p>

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

------=_Part_141_1875291675.1467973295795--

------=_Part_140_552459017.1467973295794--

.