template<typename... T>
void func()
{
for...(Ti : T) //"loop" through type pack
{
/*code there*/
}
}
switch(i)
{
for...(Ti : T)
{
case Ti::value:
Ti::f();
break; //break for `switch` not `for...`
}
}
I recently suggest similar thing but focused on variadic templates where it would be more useful:
`for...` is analogy to `sizeof...`.template<typename... T>
void func()
{
for...(Ti : T) //"loop" through type pack
{
/*code there*/
}
}
Another important thing it need to ignore `break` and `continue`. This is require to allow integrate with normal loops or switch statement:
Another thing, `for...(` is shorter than `static for(` or `for(constexpr`.switch(i)
{
for...(Ti : T)
{
case Ti::value:
Ti::f();
break; //break for `switch` not `for...`
}
}
I recently suggest similar thing but focused on variadic templates where it would be more useful:template<typename... T>
void func()
{
for...(Ti : T) //"loop" through type pack
{
/*code there*/
}
}
Another important thing it need to ignore `break` and `continue`.
switch(i)
{
for...(Ti : T)
{
case Ti::value:
Ti::f();
break; //break for `switch` not `for...`
}
}
Another thing, `for...(` is shorter than `static for(` or `for(constexpr`.
I would suggest extending unrolled for statements to allow the typedef specifier and a type-init-list (a braced-init-list of type-ids):
template<typename... Args>
void func()
{
for (typedef T : {Args...})
g<T>();
}
The semantics are clear. The declaration at the start of each block becomes a typedef of the corresponding type.
Another important thing it need to ignore `break` and `continue`.
I think break and continue should have their usual expected semantics. break jumps to the end of the last unrolled block. continue jumps to the start of the next one.
> This is require to allow integrate with normal loops or switch statement:switch(i)
{
for...(Ti : T)
{
case Ti::value:
Ti::f();
break; //break for `switch` not `for...`
}
}
The following is ill-formed:template<int x> void f() {}
int main()
{
for (constexpr int x : {1,2,3})
f<x>();
}
as constexpr cannot specify a loop variable.
Maybe we could say:for (constexpr T t : L)
is well-formed iff:constexpr T[] arr = L
is well-formed. The semantics are as if the loop is unrolled in the obvious way.
So for the original example it is as if:
int main()
{
{
constexpr int x = 1;
f<x>();
}
{
constexpr int x = 2;
f<x>();
}
{
constexpr int x = 3;
f<x>();
}
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
It's not true that we can't use 'constexpr' to specify a loop variable.
The semantics are as if the loop is unrolled in the obvious way.
If you want to force loop unrolling, it would seem much more natural to use a pack expansion.
Using a construct like 'for' would violate peoples' intuitions. 'for' does not usually imply code duplication,
a 'constexpr' variable declaration can usually have only a single value
On Thursday, October 3, 2013 10:34:12 PM UTC+2, Richard Smith wrote:It's not true that we can't use 'constexpr' to specify a loop variable.
Yes, as per my followup to Daniel I meant that it isn't effectively possible because of how range-based for is currently defined.
The semantics are as if the loop is unrolled in the obvious way.
If you want to force loop unrolling, it would seem much more natural to use a pack expansion.The purpose isn't to force unrolling, the term "unrolled" is purely for specification purposes. An implementation is free to unroll a normal loop, and is free to rollup an "unrolled" loop. It's purely the logical behaviour of the program that is specified.
Using a construct like 'for' would violate peoples' intuitions. 'for' does not usually imply code duplication,The behaviour of a program containing:
for (T x : L)
and the same one instead containing:
for (constexpr T x : L)
are identical if both well-formed. So it isn't clear how it is unintuitive. As stated the code duplication is only logical.
In the following:a 'constexpr' variable declaration can usually have only a single value
template<int x>
constexpr int g()
{
constexpr int y = x*2;
return y + 5;
}
constexpr int z1 = g<3>();
constexpr int z2 = g<4>();
The `y` constexpr variable declaration has two different values, 6 and 8.
Just like in the following:
for (constexpr int x : {3,4})
{
constexpr int y = x*2;
/* ... */
}
We can think of the inner statement of the unrolled for statement as if it were the body of a unnamed template function,
and the loop variable as a non-type template parameter. The body is instantiated and called once for each element of the constexpr array initializer.
On Thu, Oct 3, 2013 at 3:56 PM, Andrew Tomazos <andrew...@gmail.com> wrote:Yes, as per my followup to Daniel I meant that it isn't effectively possible because of how range-based for is currently defined.
It's *not* effectively impossible. To reiterate: you can pick a range type such that the code is valid. It's just not very useful.
The purpose isn't to force unrolling, the term "unrolled" is purely for specification purposes. An implementation is free to unroll a normal loop, and is free to rollup an "unrolled" loop. It's purely the logical behaviour of the program that is specified.
No, this is something different. You want the static types of elements of the loop body to be different on different iterations, for instance. That *forces* the loop to be fully unrolled.
We can think of the inner statement of the unrolled for statement as if it were the body of a unnamed template function,
Right. Making it act like a template is the thing that's new and unintuitive.
On Friday, October 4, 2013 1:17:06 AM UTC+2, Richard Smith wrote:On Thu, Oct 3, 2013 at 3:56 PM, Andrew Tomazos <andrew...@gmail.com> wrote:
Yes, as per my followup to Daniel I meant that it isn't effectively possible because of how range-based for is currently defined.
It's *not* effectively impossible. To reiterate: you can pick a range type such that the code is valid. It's just not very useful.
Yes, fine. We are in violent agreement that a constexpr-specified loop variable is currently impossible to use in a very useful way.The purpose isn't to force unrolling, the term "unrolled" is purely for specification purposes. An implementation is free to unroll a normal loop, and is free to rollup an "unrolled" loop. It's purely the logical behaviour of the program that is specified.
No, this is something different. You want the static types of elements of the loop body to be different on different iterations, for instance. That *forces* the loop to be fully unrolled.
In some cases, such as when there are varying static types dependant on the loop variable it may force the loop to be unrolled, but this would be a consequence of the intention of the code, and not grounds to claim the construct is unintuitive.
I think you may be conflating the unintuitive with the difficult-to-implement.We can think of the inner statement of the unrolled for statement as if it were the body of a unnamed template function,Right. Making it act like a template is the thing that's new and unintuitive.
Yes, it should have scope, and will not break switch because switch allow loops (and scopes) inside: http://en.wikipedia.org/wiki/Duff%27s_device (and it should work in C++ at least in g++ it still works).
That said, I think the problem is worth solving. And we already have a tool to repeatedly stamp out multiple, slightly different, copies of the same construct: pack expansion. That's the direction that I think should be pursued here. Plus, any improvements there (such as allowing pack-expansion of expression-statements, or providing pack literals) address a wide variety of problems and fit nicely with existing language constructs, rather than being something new and special-purpose.