Taking the address of an eponymous template

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Jul 31 07:52:01 PDT 2017


On 07/31/2017 01:59 PM, Arafel wrote:
> On 07/31/2017 12:14 PM, ag0aep6g wrote:
[...]
>  > You'd have to instantiate the inner template, too. Something like
>  > `&c.baz!"a".baz!()`, but that doesn't work. I don't know how you could
>  > make it work.
>  >
> I tried this as well, and couldn't make it work either. Do you know if 
> it's supposed to work? I mean, do the spec mention this?

I don't think that exact syntax is supposed to work. When you 
instantiate a non-eponymous template, you get a template instantiation 
with members which you can access. With an eponymous template, you get 
the eponymous member, nothing else. There's no way to get the members of 
the template by name then.

Ideally, I'd say this would work: `&c.baz!"a"!()`. But that's not valid 
syntax.

With a free template, you can make an alias of the first instantiation 
and then use that to instantiate the second time:

----
template baz(string S)
{
     void baz()() {}
}

alias baz1 = baz!"a";
void function() aBaz = &baz1!();
----

Could this work when the template is a class member?

----
class C
{
     template baz(string S)
     {
         void baz()() {}
     }
}

void main()
{
     C c = new C();
     alias baz1 = c.baz!"a";
     // void delegate() aBaz = &baz1!(); // doesn't work
     pragma(msg, typeof(&baz1!()));
         // void function() pure nothrow @nogc @safe
}
----

We see that `&baz!()` is a function pointer, not a delegate. Looks like 
`this` got lost along the way. No idea if this is a bug or expected.

It might be possible to hack around the issue by building the delegate 
manually:

----
C c = new C();
alias baz1 = c.baz!"a";
void delegate() aBaz;
aBaz.funcptr = &baz1!();
aBaz.ptr = cast(void*) c;
----

That *seems* to work, but I'm not at all sure if it's actually correct.

[...]
> OK, not directly with the "this" parameter... those you have to include 
> explicitly. However, this seems to be an unrelated problem: the "this T" 
> parameter seems to be only automatically deducted during function calls. 
> Even this doesn't work:
> 
> ```
> class A {
>      template foo(this T) {
>          void bar() {
>              import std.stdio;
>              writeln(typeid(T));
>          }
>      }
> }
> 
> void main() {
>      A a = new A();
>      a.foo.bar();
> }
> ```
> 
> But I think that's a completely separate issue (would that be a bug, 
> btw?) It's of course a trivial issue here, but it's just an example.
> 
> What use is it to allow "this T" parameters in raw template declarations 
> if they are not going to be automatically filled?

I don't think it's a bug. The spec says that "TemplateThisParameters are 
used in member function templates" [1]. And it only shows the feature 
working with calls. So that's apparently the only case that has been 
considered and is expected to work.

It might be worthwhile to explore if the feature can be expanded beyond 
calls. No idea what the difficulties would be.

[...]
>  > So how about a function literal:
>  >
>  >      void delegate() aBaz = () => c.baz!(int, float)();
>  >
> Yeah, that's the solution I was thinking about, but I don't know how 
> much of a performance hit the extra function call would be... would the 
> function literal extra indirection layer be eventually optimised out?

I don't know.


[1] https://dlang.org/spec/template.html#template_this_parameter


More information about the Digitalmars-d-learn mailing list