Tuple IFTI with implicit conversions

Reiner Pope some at address.com
Fri Oct 19 22:03:39 PDT 2007


(A follow-up from "Any ideas for lazy evaluation on varaible argument 
functions?")

Daniel Keep wrote:
> Sadly, I don't think there's any way to fix this.  The problem is that
> if you've got IFTI (which is what allows you to omit the explicit
> template instantiation), the arguments can't be very complex.  What you
> would need is something like this:
> 
> void infoF(A...)(lazy DecayStaticArrays!(A) a) { ... }
> 
> Where "DecayStaticArrays" turns all statically-sized arrays into
> dynamically-sized ones: so (char[2u], char[6u]) would become (char[],
> char[]).

This kind of problem with IFTI seems to come up from time to time. I 
think the general case of this problem is when you want the parameter 
types[1] to be something which the argument types[1] are implicitly 
convertable to. This could be like the example above (where char[6u] is 
implicitly convertable to lazy char[]) or perhaps some function which 
takes the biggest integer type of the parameters:

BiggestIntType!(A) max(A...)(BiggestIntType!(A)[] params...) { ... }

Unfortunately, the above function won't work with IFTI. Normally, the 
"standard" solution to this would be to have a wrapper template:

BiggestIntType!(A) max(A...)(A a) {
     max_impl!(A)(a);
}

BiggestIntType!(A) max_impl(A...)(BiggestIntType!(A)[] params...) { ... }

so that the wrapper ensures IFTI still works, and it simply passes on 
the argument types to the wrapper. Although this solution works here, it 
doesn't solve Daniel's problem, and it ends up being repeated whereas I 
think the language should essentially support doing it for you.

More valuable would be the existence of some tuple in a function 
template which was a tuple of the argument types[1] for a function. I'm 
not fussed about the syntax, but the point is that argtypes is simple to 
evaluate: just take typeof() of each of the argument expressions at the 
call-site, and stick them together as a tuple. Since there's no pattern 
matching involved, IFTI can't fail. So, the examples above would become:

BiggestIntType!(A) max (argtypes A)(BiggestIntType!(A)[] params...) { ... }

and

void infoF(argtypes A)(lazy DecayStaticArrays!(A) a) { ... }

They look almost exactly the same, but the argtypes syntax says to the 
compiler, "don't try to pattern-match the parameters against lazy 
DecayStaticArrays!(A), instead just tell me what they are." Supposing 
you used the above syntax, then it would have the rules:
   1. The argtypes parameter must always go last, even after variadic 
parameters
   2. It is impossible to manually instantiate an argtypes parameter.

What do you think?

---
[1]: Here's what I mean when I distinguish parameter and argument types:

     void foo(long x) { ... }

     void main()
     {
         int y;
         foo(y);
     }

Here, I call long the parameter type, and int the argument type. The 
distinction is that the argument type is the type of the expression at 
the call site.


    -- Reiner



More information about the Digitalmars-d mailing list