Template Usage with Eponymous Trick

ShadoLight ettienne.gilbert at gmail.com
Thu Jan 30 15:14:43 UTC 2020


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);
}



More information about the Digitalmars-d-learn mailing list