Can't understand templates

H. S. Teoh via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Nov 28 11:43:42 PST 2014


On Fri, Nov 28, 2014 at 07:32:38PM +0000, Sly via Digitalmars-d-learn wrote:
> Here is an example from the tutorial:
[...]
> Point!T getResponse(T: Point!T)(string question) {
>       writefln("%s (Point!%s)", question, T.stringof);
>       auto x = getResponse!T(" x");
>       auto y = getResponse!T(" y");
>       return Point!T(x, y);
> }
[...]
> I don't understand how to read this signature: Point!T
> getResponse(T: Point!T)(string question). Clearly it's not
> supposed to be saying that T is subclass of Point!T, so those Ts
> must refer to different types. But when I rename it to
> getResponse(U: Point!T) I get a compilation error (unknown
> identifier T).

This syntax is a little confusing, but basically the ":" there is saying
"this type, when instantiated with the following pattern, produces a
valid type". Essentially it's equivalent to:

	Point!T getResponse(T)(string question)
		if (is(typeof(Point!T))) // i.e., Point!T is a valid type
	{
		...
	}


> Another question: say I have a template class Pair:
> 
> class Pair(A, B) {
>       A a;
>       B b;
>       this(A a, B b) {this.a = a; this.b = b;}
> }
> 
> How to write a specialization for getResponse matching Pair!(A, B)
> with any type arguments A and B? I tried this:
> 
> T getResponse(T)(string question)
>       if (is(T: Pair!(A, B), A, B))
> {
>       auto a = getResponse!A(" a");
>       auto b = getResponse!B(" b");
>       return new Pair!(A, B)(a, b);
> }
> 
> but get a compile error:
> 
> error: d.getResponse called with argument types (string) matches
> both:
> 	d.d(19): getResponse(T)(string question)
> and:
> 	d.d(40): getResponse(T)(string question) if (is(T : Pair!(A, B),
> A, B))

Yes, because D does not support overlapping template overloads.  Both
the original overload of getResponse and the new overload matches the
given arguments, so it's an error. You need to explicitly restrict the
original overload so that it does *not* match in the case a Pair is
given. For example:

	// Original overload
	Point!T getResponse(T : Point!T)(string question)
		if (!is(T : Pair!(A, B), A, B))
		// ^^^ this says, match all T's for which Point!T is a
		// valid type, but not when T is also an instantiation
		// of Pair!(A,B).
	{
		...
	}

	// New overload
	T getResponse(T)(string question)
		if (is(T : Pair!(A, B), A, B))
	{
		...
	}


T

-- 
It is impossible to make anything foolproof because fools are so ingenious. -- Sammy


More information about the Digitalmars-d-learn mailing list