foreach on a tuple using aliases

Alex sascha.orlov at gmail.com
Sun Aug 5 14:48:55 UTC 2018


On Sunday, 5 August 2018 at 14:07:30 UTC, Steven Schveighoffer 
wrote:
> I have found something that looks like a bug to me, but also 
> looks like it could simply be a limitation of the foreach 
> construct.
>
> Consider this code:
>
> struct Foo {}
>
> enum isFoo(alias x) = is(typeof(x) == Foo);
>
> void main()
> {
>     Foo foo;
>     assert(isFoo!foo);
>     static struct X { int i; Foo foo; }
>     X x;
>     foreach(i, ref item; x.tupleof)
>         static if(is(typeof(item) == Foo))  // line A
>             static assert(isFoo!item);      // line B
>         else
>             static assert(!isFoo!item);
> }
>
> Consider just the two lines A and B. If you saw those lines 
> anywhere, given the isFoo definition, you would expect the 
> assert to pass. But in this case, it fails.
>
> What is happening is that the first time through the loop, we 
> are considering x.i. This is an int, and not a Foo, so it 
> assigns false to the template isFoo!item.
>
> The second time through the loop on x.foo, the compiler decides 
> that it ALREADY FIGURED OUT isFoo!item, and so it just 
> substitutes false, even though the item in question is a 
> different item.
>
> So is this a bug? Is it expected? Is it too difficult to fix?
>
> The workaround of course is to use x.tupleof[i] when 
> instantiating isFoo. But it's a bit ugly. I can also see other 
> issues cropping up if you use `item` for other meta things.
>
> -Steve

Another workaround would be
´´´
void main()
{
     Foo foo;
     assert(isFoo!foo);
     static struct X { int i; Foo foo; }
     X x;
     static foreach(i, item; typeof(x).tupleof)
         static if(is(typeof(item) == Foo))  // line A
             static assert(isFoo!item);      // line B
         else
             static assert(!isFoo!item);
}
´´´
wouldn't it?


More information about the Digitalmars-d-learn mailing list