digitalmars.D.learn - Implicit Function Template Instantiation (IFTI) Question
- jmh530 (38/38) Apr 27 2020 When using a template with multiple functions within it, is it
- Steven Schveighoffer (30/76) Apr 27 2020 foo!int aliases to the template foo's inside, so you are already in ther...
- jmh530 (11/12) Apr 27 2020 Thanks for that. Very detailed.
- H. S. Teoh (17/22) Apr 27 2020 Yes, when the template is eponymous, the name of the template becomes
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 }
Apr 27 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 foofoo!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 throughNo, 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)); // truewriteln(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
Apr 27 2020
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.
Apr 27 2020
On Mon, Apr 27, 2020 at 05:19:35PM +0000, 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
Apr 27 2020