Implicit Function Template Instantiation (IFTI) Question

Steven Schveighoffer schveiguy at gmail.com
Mon Apr 27 17:40:06 UTC 2020


On 4/27/20 1:19 PM, jmh530 wrote:
> When using a template with multiple functions within it, is it possible 
> to access the underlying functions directly? Not sure I am missing 
> anything, but what works when the functions are named differently from 
> the headline template doesn't work when the functions are named the same.
> 
> import std.stdio: writeln;
> import std.traits: isFunction;
> 
> template foo(T) {
>      void foo(U)(U x) {
>          writeln("here0");
>      }
> 
>      void foo(U, V)(U x, V y) {
>          writeln("there0");
>      }
> }
> 
> template bar(T) {
>      void baz(U)(U x) {
>          writeln("here1");
>      }
> 
>      void baz(U, V)(U x, V y) {
>          writeln("there1");
>      }
> }
> 
> void foobar(T)(T x) {}
> 
> void main() {
>      foo!int.foo!(float, double)(1f, 2.0); //Error: template foo(U)(U x) 
> does not have property foo

foo!int aliases to the template foo's inside, so you are already in there.

In reality, you should want to use foo!int!(float, double), but that 
does not parse.

You can do:

alias x = foo!int;
x!(float, double)(...)

or you can just use IFTI:

foo!int(1f, 2.0);

>      writeln(isFunction!(foo!int)); //prints false, as expected b/c not 
> smart enough to look through

No, because the template hasn't been instantiated. Note that 
isFunction!(foobar) prints false also.

>      writeln(isFunction!(foo!int.foo!float)); //Error: template 
> identifier foo is not a member of template onlineapp.foo!int.foo(U)(U x)

An eponymous template is equivalent to the members that have the same 
name. There is no way to access the template namespace (this was changed 
some time ago).

with x definition above:

writeln(isFunction!(x!float)); // true

>      writeln(isFunction!(foo!int.foo!(float, double))); //ditto
> 
>      bar!int.baz!(float, double)(1f, 2.0); //prints there1
>      writeln(isFunction!(bar!int.baz!(float, double))); //prints true
> 
>      writeln(isFunction!(foobar!int)); //prints true
> }
> 
> 

Generally it's just fine to do foo(T, U, V) and dispense with the double 
templates, as IFTI will take care of the other two.

The main reason to have nested templates is when you need to bind the 
explicit template parameters to a variadic, and the IFTI parameters to 
something else.

i.e.:

template foo(T...)
{
     void foo(U...)(U args) {... }
}

foo!(int, char, bool)(1, 2, 3) -> foo!(int, char, bool)!(int, int, 
int)(1, 2, 3);

I hope this clears it up a bit.

-Steve


More information about the Digitalmars-d-learn mailing list