On Tue, Mar 12, 2019 at 03:26:05PM +0000, Victor Porton via Digitalmars-d-learn wrote: [...] > On Tuesday, 12 March 2019 at 09:05:36 UTC, Nicholas Wilson wrote: [...] > > template FieldInfo(T) { > > template FieldInfo(Nullable!(T) default_) > > { > > enum FieldInfo = 0; > > } > > } > > > > seems to work, but I can't seem to instantiate one of it. > > Why you use the same name "FieldInfo" for both the template and its > subtemplate? Does it make some sense?
This is a D idiom called the "eponymous template". Whenever the template contains a member of the same name as the template, it's an eponymous template, and you can refer directly to the member by the template name, rather than using templateName.memberName. For example, a template function is usually written like this: ReturnType myFunc(TemplateArgs...)(RuntimeArgs args...) { ... // implementation here } This is actually shorthand for the eponymous template: template myFunc(TemplateArgs...) { ReturnType myFunc(RuntimeArgs args...) { ... // implementation here } } Similarly, when you write: enum isInputRange(T) = hasMember!(T, empty) && ... that's actually shorthand for: template isInputRange(T) { enum isInputRange = hasMember!(T, empty) && ... } The eponymonus template idiom allows you to use a single name to refer to both the template and the member. Without this idiom, you'd have to use the very verbose notation: static if (isInputRange!T.isInputRange) ... or auto retval = myFunc!(A, B, C).myFunc(1, 2, 3); T -- It won't be covered in the book. The source code has to be useful for something, after all. -- Larry Wall