www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Aliasing current function template instance

reply Jean-Louis Leroy <jl leroy.nyc> writes:
Is it possible, inside a function template, to create an alias to 
the instantiated function? IOW the equivalent of __FUNCTION__, 
but yielding an alias?

The closest I came is:

   import std.string;
   import std.traits;

   void foo(T)(lazy T)
   {
     mixin(
       "alias thisFunction = ",
       __FUNCTION__[0..__FUNCTION__.lastIndexOf('.')],
       ";");
     pragma(msg, Parameters!thisFunction);
   }

   void main()
   {
     foo(0);
     foo("");
   }

   dmd -c aliasthisfunction.d
   (lazy int)
   (lazy string)

...but (unsurprisingly) this fails in presence of overloads. I.e. 
if I throw in:

   void foo(T)(int, T);

...then I get:

   aliasthisfunction.d(6): Error: template `aliasthisfunction.foo` 
matches more than one template declaration:
   aliasthisfunction.d(4):     `foo(T)(lazy T)`
   and
   aliasthisfunction.d(20):     `foo(T)(int, T)`
   ...

Something I have overlooked? Any ideas?
May 01 2020
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/1/20 4:28 PM, Jean-Louis Leroy wrote:

 Something I have overlooked? Any ideas?
 
This trick works. No idea who came up with it: alias thisFunction = __traits(parent, {}); -Steve
May 01 2020
parent Jean-Louis Leroy <jl leroy.nyc> writes:
On Friday, 1 May 2020 at 20:43:05 UTC, Steven Schveighoffer wrote:
 On 5/1/20 4:28 PM, Jean-Louis Leroy wrote:

 Something I have overlooked? Any ideas?
 
This trick works. No idea who came up with it: alias thisFunction = __traits(parent, {}); -Steve
I think I get the idea. Alas it doesn't work inside a function template, because it returns the template, not the instance: void foo(T)(lazy T) { alias thisFunction = __traits(parent, {}); pragma(msg, thisFunction.stringof); //pragma(msg, Parameters!thisFunction); // later } void main() { foo(0); foo(""); } prints: foo(T)(lazy T) foo(T)(lazy T) Uncommenting the line that is (more or less) my real goal: aliasthisfunction.d(7): Error: template instance `std.traits.Parameters!(foo)` does not match template declaration `Parameters(func...)` with `func = (foo(T)(lazy T))` must satisfy the following constraint: ` isCallable!func`
May 01 2020
prev sibling next sibling parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Friday, 1 May 2020 at 20:28:58 UTC, Jean-Louis Leroy wrote:
 Is it possible, inside a function template, to create an alias 
 to the instantiated function? IOW the equivalent of 
 __FUNCTION__, but yielding an alias?

 The closest I came is:

   import std.string;
   import std.traits;

   void foo(T)(lazy T)
   {
     mixin(
       "alias thisFunction = ",
       __FUNCTION__[0..__FUNCTION__.lastIndexOf('.')],
       ";");
     pragma(msg, Parameters!thisFunction);
   }

   void main()
   {
     foo(0);
     foo("");
   }

   dmd -c aliasthisfunction.d
   (lazy int)
   (lazy string)

 ...but (unsurprisingly) this fails in presence of overloads. 
 I.e. if I throw in:

   void foo(T)(int, T);

 ...then I get:

   aliasthisfunction.d(6): Error: template 
 `aliasthisfunction.foo` matches more than one template 
 declaration:
   aliasthisfunction.d(4):     `foo(T)(lazy T)`
   and
   aliasthisfunction.d(20):     `foo(T)(int, T)`
   ...

 Something I have overlooked? Any ideas?
This should work: alias context(alias a) = __traits(parent, a); void fun() { alias ctx = context!({})(); } {} becomes a lambda inside fun(), so it's parent is fun(). The same could be done by introducing a symbol explicitly, but that pollutes the namespace. This template works inside functions, methods, lambdas, modules, structs, classes and interfaces. -- Simen
May 01 2020
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 1 May 2020 at 20:28:58 UTC, Jean-Louis Leroy wrote:
 Something I have overlooked? Any ideas?
There's an old rule, that I can't find in the spec anymore but I'm still pretty sure it is there, where taking the address of a template inside a template yields the current instantiation. Then you can fetch the type of that and do some reflection off. So try this in your test rig: pragma(msg, Parameters!(typeof(&foo))); This rule was in there to ease callbacks and recursive functions iirc but it can also work with you thanks to typeof turning the runtime address back into a compile time alias.
May 01 2020
parent Jean-Louis Leroy <jl leroy.nyc> writes:
On Friday, 1 May 2020 at 21:05:17 UTC, Adam D. Ruppe wrote:
 On Friday, 1 May 2020 at 20:28:58 UTC, Jean-Louis Leroy wrote:
 Something I have overlooked? Any ideas?
There's an old rule, that I can't find in the spec anymore but I'm still pretty sure it is there, where taking the address of a template inside a template yields the current instantiation. Then you can fetch the type of that and do some reflection off. So try this in your test rig: pragma(msg, Parameters!(typeof(&foo))); This rule was in there to ease callbacks and recursive functions iirc but it can also work with you thanks to typeof turning the runtime address back into a compile time alias.
It looks like it does the trick. Thanks! Trying to add support for method templates to openmethods.
May 01 2020