Thread overview
Why a template with Nullable does not compile?
Mar 12, 2019
Victor Porton
Mar 12, 2019
Victor Porton
Mar 12, 2019
Nicholas Wilson
Mar 12, 2019
Victor Porton
Mar 12, 2019
H. S. Teoh
Mar 12, 2019
Victor Porton
Mar 12, 2019
H. S. Teoh
Mar 12, 2019
Victor Porton
March 12, 2019
Why does this not compile?

import std.typecons;

template FieldInfo(T, Nullable!T default_) {
}

/usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(2570,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(3291,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set

March 12, 2019
On Tuesday, 12 March 2019 at 05:14:21 UTC, Victor Porton wrote:
> Why does this not compile?
>
> import std.typecons;
>
> template FieldInfo(T, Nullable!T default_) {
> }
>
> /usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(2570,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set
> /usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(3291,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set

LDC - the LLVM D compiler (1.11.0):
  based on DMD v2.081.2 and LLVM 6.0.1

March 12, 2019
On Tuesday, 12 March 2019 at 05:14:21 UTC, Victor Porton wrote:
> Why does this not compile?
>
> import std.typecons;
>
> template FieldInfo(T, Nullable!T default_) {
> }
>
> /usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(2570,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set
> /usr/lib/ldc/x86_64-linux-gnu/include/d/std/typecons.d(3291,17): Error: `alias T = T;` cannot alias itself, use a qualified name to create an overload set

It seems to be getting confused between the two types of Nullable, namely:
Nullable(T), and
Nullable(T, T defaultVal)

template FieldInfo(T) {
    template FieldInfo(Nullable!(T) default_)
    {
        enum FieldInfo = 0;
    }
}

seems to work, but I can't seem to instantiate one of it.

March 12, 2019
template FieldInfo(T, Nullable!T default_) {
}

On Tuesday, 12 March 2019 at 09:05:36 UTC, Nicholas Wilson wrote:
> It seems to be getting confused between the two types of Nullable, namely:
> Nullable(T), and
> Nullable(T, T defaultVal)

I don't understand why exactly it is getting confused. How can it decide that "Nullable!T default_" is a two-arguments template when it is so not "Nullable!(T, default_)"? Please explain the EXACT cause of the error.

> 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?
March 12, 2019
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
March 12, 2019
On Tuesday, 12 March 2019 at 16:20:11 UTC, H. S. Teoh wrote:
> 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);

I know what is eponymous template. But how it behaves when the eponymous member inside itself is also a template? How to instantiate it? (provide please an example how to instantiate)
March 12, 2019
On Tue, Mar 12, 2019 at 04:23:29PM +0000, Victor Porton via Digitalmars-d-learn wrote: [...]
> I know what is eponymous template. But how it behaves when the eponymous member inside itself is also a template? How to instantiate it? (provide please an example how to instantiate)

You need to provide two sets of template arguments. Usually, the only time we nest eponymous templates this way is when we're writing a function that needs to take two variadic sets of template parameters. In that case, we only need to write one set of template parameters and let IFTI fill in the second set of parameters for us.

For example:

	template map(funcs...) {
		template map(Ranges...) {
			auto map(Ranges rr) {
				...
			}
		}
	}

	auto r = map!(func1, func2)(r1, r2);

The first part `map!(func1, func2)` resolves to an instantiation of the
outer template, which is an inner template, then the compiler uses IFTI
to deduce the second set of arguments as !(typeof(r1), typeof(r2)) in
order to instantiate the inner template.

If you want to instantiate it by hand, you could do something like this:

	alias Outer = map!(func1, func2);	// instantiate outer template
	alias inner = Outer!(int[], int[]);	// instantiate inner template
	inner([ 1, 2, 3], [ 4, 5, 6 ]);


T

-- 
People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG
March 12, 2019
On Tuesday, 12 March 2019 at 15:26:05 UTC, Victor Porton wrote:
> template FieldInfo(T, Nullable!T default_) {
> }
>
> On Tuesday, 12 March 2019 at 09:05:36 UTC, Nicholas Wilson wrote:
>> It seems to be getting confused between the two types of Nullable, namely:
>> Nullable(T), and
>> Nullable(T, T defaultVal)
>
> I don't understand why exactly it is getting confused. How can it decide that "Nullable!T default_" is a two-arguments template when it is so not "Nullable!(T, default_)"? Please explain the EXACT cause of the error.

My question why it is getting confused was not answered.