Specialization - Major hole in the spec?

Peter Alexander peter.alexander.au at gmail.com
Wed Jan 4 16:47:12 PST 2012


I've had a look through the spec, as well as TDPL. Andrei's book 
mentions nothing about template specialization, and the website is 
scarce on the details. In particular, nothing is mentioned about the 
interplay between specialization and overloading -- something that is 
very often misunderstood in C++.

I have three questions:

-----------------------------------------------------------------------

Question 1: Is a function specialization's signature required to match 
the primary template signature like in C++? e.g.

void foo(T)(T t);           // 1
void foo(T : float)(int t); // 2

Is this legal? DMD allows it. If so, what should these calls do?

foo(0);          // 1
foo(0.0f);       // 1
foo!int(0);      // 1
foo!int(0.0f);   // error
foo!float(0);    // 2
foo!float(0.0f); // 1 (!)

DMD's results are in the comments.

I find it surprising that the last call doesn't use the specialization 
even though I explicitly requested it. The spec says "The template 
picked to instantiate is the one that is most specialized that fits the 
types of the TemplateArgumentList." My interpretation of that says that 
it should use the specialization.

Note: The equivalent is simply illegal in C++

template <typename T> void foo(T t) {}
template <>           void foo<float>(int t) {}

The specialization signature is required to match the primary template.

-----------------------------------------------------------------------

Question 2: How do specializations and overloads play together?

Example:

void foo(T)(T t);  // 1
void foo(T)(T* t); // 2
void foo(int* t);  // 3

foo(new int); // what does this call?

void foo(T)(T t);  // 1
void foo(int* t);  // 3
void foo(T)(T* t); // 2

foo(new int); // what does this call now that 2 & 3 are swapped?

People that know their C++ will recognize this as the Dimov/Abrahams 
example. The equivalent code in C++ calls 3 in the first case and 2 in 
the second because of the way overloads and specializations work. Yes, 
it depends on the order you write the functions. See 
http://www.gotw.ca/publications/mill17.htm for more details.

DMD currently gives an error saying that function 3 conflicts with 
function 1. Is this correct? Why?

-----------------------------------------------------------------------

Question 3: When specializing, am I required to keep using T instead of 
what it is specialized to?

A couple of illustrating examples:

void foo(T)(T t);       // 1
void foo(T : int)(T t); // 2

foo(0); // DMD calls 2 as expected


void bar(T)(T t);         // 1
void bar(T : int)(int t); // 2

bar(0); // DMD calls 1 (!)

What are the rules here? Is DMD correct? I find this behavior very 
surprising.

-----------------------------------------------------------------------

This all needs to be clarified because from what I can tell, the way 
specialization currently works in D is completely different from how it 
works in C++.


More information about the Digitalmars-d mailing list