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

Reply via email to