On Thursday, 30 January 2020 at 14:22:11 UTC, Paul Backus wrote:
On Thursday, 30 January 2020 at 14:10:38 UTC, ShadoLight wrote:
...but in the 'classical' default template style, so I would have thought the template_name!(compile_time_args).function_name(run_time_args) style would still work, even if the template and function names are identical.

If this is in fact now the intended behavior, then there are some places where the documentation are in error.


[1]: https://dlang.org/spec/template.html#variadic-templates

Eponymous templates are documented here:

https://dlang.org/spec/template.html#implicit_template_properties

This specific behavior is documented in the first paragraph below that heading, which reads as follows:

If a template contains members whose name is the same as the template identifier and if the type or the parameters type of these members include at least all the template parameters then these members are assumed to be referred to in a template instantiation

Yes, the behavior is described but not that it is in fact the _only_ way that an eponymous template can in fact be instantiated.

I think this behavior will be surprising for someone new to D. For eponymous templates you actually have the short-hand declarative style as well...

        void foo(S, T)(S s, T t) {}

..ok, needs to call with...
        foo!(int, int) (1, 2);
...or even just...
        foo(1, 2);
...and your template parameters will be deduced.

This is at least kind-of intuitive. But now if you declare the template in the fully standard way:

       template foo(S, T)
       {
           void foo(S s, T t) {}
       }

..and you call it in the completely standard way (as you would have in fact been required if template identifier and member were differently named)...
       foo!(int, int).foo(1, 2);
..it not only does _not_ compile, but gives you an error:

onlineapp.d(12): Error: function onlineapp.foo!(int, int).foo(int s, int t) is not callable using argument types ()

...where foo!(int, int).foo(int s, int t) is clearly a match!

I really like the eponymous template trick and all that, but this did catch me by surprise -I did not realize that the eponymous template style in fact invalidates the 'classic' template invocation style: it is one or the other. I was somehow under the mistaken impression that you could still revert to the classic style, even if your template identifier and member identifier were identical.

Is there a technical reason for this limitation? Why are the 'classical' invocation style not allowed for eponymous templates as well?

It seems somewhat arbitrary - note that inner/outer functions does not have this limitation - the fllowing is legal and compiles (and does not lead to infinite recursion):

int foo(int a, int b)
{
    int foo(int x, int y) {return x+y;}
    return foo(a, b);
}


void main()
{
   int z = foo(2, 4);
}

Reply via email to