Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread jmh530 via Digitalmars-d-learn
On Monday, 27 April 2020 at 17:40:06 UTC, Steven Schveighoffer 
wrote:

[snip]


Thanks for that. Very detailed.

In terms of a use case, we just added a center function to mir 
[1]. It can take an alias to a function. I wanted to add a check 
that the arity of the function was 1, but it turned out that I 
couldn't do that for mean [2] because it has a similar structure 
as what I posted and arity relies on isCallable, which depends on 
isFunction.



[1] http://mir-algorithm.libmir.org/mir_math_stat.html#.center
[2] http://mir-algorithm.libmir.org/mir_math_stat.html#.mean



Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Apr 27, 2020 at 05:19:35PM +, jmh530 via Digitalmars-d-learn wrote:
> When using a template with multiple functions within it, is it
> possible to access the underlying functions directly?

Yes, but only if the template is not eponymous.


> 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.

Yes, when the template is eponymous, the name of the template becomes
the name of the eponymous member, and thus effectively hides the other
members from outside access.

This is actually useful when you want to write a template function with
internal implementation details that outside code cannot access no
matter what.  It's like a little encapsulation unit locked away behind
the public-facing eponymous member. I've used this on a few occasions
when I wanted template implementation details to be invisible even to
other code inside the same module.

(Interesting note: you can even stick unittests inside the template
block to test internal details, while still keeping said details away
from prying eyes in the rest of the module. :-P)


T

-- 
Doubtless it is a good thing to have an open mind, but a truly open mind should 
be open at both ends, like the food-pipe, with the capacity for excretion as 
well as absorption. -- Northrop Frye


Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread jmh530 via Digitalmars-d-learn
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
writeln(isFunction!(foo!int)); //prints false, as expected 
b/c not smart enough to look through
writeln(isFunction!(foo!int.foo!float)); //Error: template 
identifier foo is not a member of template 
onlineapp.foo!int.foo(U)(U x)

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
}