New operators opStaticIndex and friends

Simen Kjærås simen.kjaras at gmail.com
Thu May 16 08:28:35 UTC 2019


On Wednesday, 15 May 2019 at 20:04:29 UTC, Exil wrote:
> On Wednesday, 15 May 2019 at 09:05:20 UTC, Simen Kjærås wrote:
>> On Wednesday, 15 May 2019 at 01:42:57 UTC, Exil wrote:
>>> Does it need to be called opStaticIndex? Could it just be 
>>> called opIndex and require the specific template arguments. 
>>> If you define opIndex(int)() now, it will never be called 
>>> right (unless you specifically invoke it)?
>>
>> Correct. But opIndex(T...)(Foo!T t) may be, and could then be 
>> called as either
>>
>>     s[0](Foo!0.init)
>>
>> or
>>
>>     s[Foo!0.init]
>>
>> Not sure if this is a big issue, but it's at least indicative 
>> of possible other issues.
>>
>> --
>>   Simen
>
>
>     s[0](Foo!0.init) // -> s.opIndex!(0)()(Foo!0.init)
>     s[Foo!0.init]    // -> s.opIndex(Foo!0.init);
>
> If it compiled would entire depend on what opIndex returns, the 
> arguments passed to opIndex() are the values in "[]" not the 
> brackets, which is a separate call.
>
> Unless you meant this?
>
>     s[0, Foo!0.init];
>
> Which would then be difficult to know which function to call as 
> it takes in a compile-time value and a run-time value.

I meant exactly what I wrote. Since s[0] would be compile-time, 
the arguments passed to opIndex would indeed be 0. This would 
evaluate to a function taking a Foo!0. We could define that to be 
immediately called with no run-time arguments, but that 
complicates certain patterns that may be of interest:

struct S {
     template opIndex(size_t idx) {
         static if (idx == 0) alias opIndex = fun1;
         else alias opIndex = fun2;
     }

     void fun1(size_t i)(Foo!i value) {}
     void fun2() {}
}

S s;
s[0](Foo!0.init); // Should call fun1 with Foo!0.init.
s[1](); // Should call fun2 with no args.

If immediate call was implemented, the above would look like this:

struct S {
     auto opIndex(size_t idx)() {
         static if (idx == 0) return &fun1!idx;
         else return &fun2;
     }

     void fun1(size_t i)(Foo!i value) {}
     void fun2() {}
}

Suddenly I'm dealing with function pointers instead of aliases, 
and this forces you to special-case functions while values, 
types, and aliases to everything but functions follow the same 
pattern.

Of course, if no run-time arguments were given and there is no & 
operator before s[0], calling the returned function immediately 
might be the sane thing to do.

--
   Simen


More information about the Digitalmars-d mailing list