Extend the call site default argument expansion mechanism?

Simen Kjærås simen.kjaras at gmail.com
Wed May 16 09:01:29 UTC 2018


On Tuesday, 15 May 2018 at 15:02:36 UTC, jmh530 wrote:
> On Tuesday, 15 May 2018 at 14:52:46 UTC, Steven Schveighoffer 
> wrote:
>> [snip]
>>
>> It seems opDispatch isn't being used in the with statement. 
>> That seems like a bug, or maybe a limitation. I'm not sure how 
>> "with" works, but I assumed it would try calling as a member, 
>> and then if it doesn't work, try the call normally. Probably 
>> it's checking to see if it has that member first.
>>
>> Annoying...
>>
>> -Steve
>
> Looks like with statements ignore opDispatch.
>
> struct Foo(int x)
> {
>     auto opDispatch(string s)()
>         if (s == "bar")
>     {
>         return x++;
>     }
> }
>
>
> void main()
> {
>     int y = 0;
>     with(Foo!1)
>     {
>         y = bar; //error: undefined identifier bar
>     }
>     assert(y == 2);
> }

You've got bugs in your code: ++x has to fail for the template 
case, since you're trying to increment a compile-time value. This 
is what the call to bar is lowered to:

     Foo!1.opDispatch!"bar"()

When you try and compile that, you get these error messages:

Error: cannot modify constant 1
Error: template instance `foo.Foo!1.Foo.opDispatch!"bar"` error 
instantiating

In addition, the with-statement in your code refers to the type 
Foo!1, not an instance of it. Fixed code:

     struct Foo(int x)
     {
         int n = x;
         auto opDispatch(string s)()
             if (s == "bar")
         {
             n++;
             return n;
         }
     }


     unittest
     {
         int y = 0;
         with(Foo!1())
         {
             y = bar; // Works!
         }
         assert(y == 2);
     }

--
   Simen


More information about the Digitalmars-d mailing list