Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
May 01, 2020 Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
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 Re: Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jean-Louis Leroy | 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 Re: Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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 Re: Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jean-Louis Leroy | 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 Re: Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jean-Louis Leroy | 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 Re: Aliasing current function template instance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
|
Copyright © 1999-2021 by the D Language Foundation