foreach on a tuple using aliases

Timon Gehr timon.gehr at gmx.ch
Sun Aug 5 15:40:13 UTC 2018


On 05.08.2018 16:07, 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?

It's a bug. The two copies of 'item' are not supposed to be the same 
symbol. (Different types -> different symbols.)

> Is it too difficult to fix?
> ...

Unlikely.

> 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



More information about the Digitalmars-d-learn mailing list