class template specialization and inheritance

Sean Kelly sean at invisibleduck.org
Wed May 14 08:44:24 PDT 2008


mki wrote:
> Sean Kelly Wrote:
> 
>> == Quote from mki (none at none.com)'s article
>>> Hello!
>>> I just discovered the template syntax of D. I am very exited about its simplicity compared to C++.
>>> Now I ran into a template behavior I do not understand. This code:
>>> *** begin code 1 ***
>>> import std.stdio;
>>> class A { }
>>> class B : A { }
>>> class C(T:A) {
>>>     static void tellMe() {
>>>         writefln("derived from A.");
>>>     }
>>> }
>>> class C(T) {
>>>     static void tellMe() {
>>>         writefln("generic.");
>>>     }
>>> }
>>> void main() {
>>>     C!(A).tellMe();
>>>     C!(B).tellMe();
>>>     C!(int).tellMe();
>>> }
>>> *** end code 1 ***
>>> as expected produces the output:
>>> derived from A.
>>> derived from A.
>>> generic.
>>> But this code
>>> *** begin code 2 ***
>>> import std.stdio;
>>> class A(T) { }
>>> class B(T) : A!(T) { }
>>> class C(TT:A!(T)) {
>>>     static void tellMe() {
>>>         writefln("derived from A!(T).");
>>>     }
>>> }
>>> class C(T) {
>>>     static void tellMe() {
>>>         writefln("generic.");
>>>     }
>>> }
>>> void main() {
>>>     C!(A!(int)).tellMe();
>>>     C!(B!(int)).tellMe();
>>>     C!(int).tellMe();
>>> }
>>> *** end code 2 ***
>>> gives the output:
>>> derived from A!(T).
>>> generic.
>>> generic.
>>> In the second line I would expect the output "derived from A!(T)", like in the example of code 1. My feeling is that
>> for C!(B!(int))
>>> 'class C(TT:A!(T))'
>>> with TT=B!(T) and T=int should be a better specialization than
>>> 'class C(T)'
>>> with T=B!(T).
>>> Why is 'class C(T)' chosen here?
>> I believe that template expansion like the above requires an exact match for specialization, so
>> it's basically the same as C++ in this respect.  However, I do think that this is confusing in light
>> of the "is" syntax where a colon means something different.
> 
> In the article
> http://www.digitalmars.com/d/2.0/templates-revisited.html
> I found the example
> 
> class Foo(
>   R,            // R can be any type
>   P:P*,         // P must be a pointer type
>   T:int,        // T must be int type
>   S:T*,         // S must be pointer to T
>   C:B,          // C must be of class B or derived
>                 // from B
>   U:I,          // U must be a class that
>                 // implements interface I
>   string str = "hello",
>                 // string literal,
>                 // default is "hello"
>   alias A = B   // A is any symbol
>                 // (including template symbols),
>                 // defaulting to B
>   )
> 
> So according to the comment in the 6th line the colon includes inherited classes.
> Also, in my example "code 1" the colon works this way:
> Since the second line of the output is
> "derived from A."
> C!(B) matches the expression C(T:A) with T=B
> 
> It seems that the additional template parameter T of class A somehow makes a difference in "code 2". But I still don't see why this should be.

Oops, you're right.  Shows how often I specialize templates on classes 
:-p  In any case, I think the current compiler simply treats the "T" in 
"C(TT : A!(T))" as an unknown specific type rather than a placeholder 
for "any" type.  I tried converting the declaration to "C(TT:A!(int))" 
and it worked as desired.  And unfortunately I don't think D supports 
template template parameters so you couldn't do something like 
"C(T!(U):A!(U))" either, even if you knew that the type being passed 
only had one template parameter.  Personally, I think this is a bit of a 
hole in D's template mechanism.  It would be nice if there were a way to 
break apart template parameter types and determine the component types 
and such easily.  Something like:

     class C( T1!(x = ...), int n : 1 = x.length, T2 : int = x[0] ) {}

Where 'x' becomes a tuple holding all the template parameters of T1. 
This wouldn't exactly resolve your specific situation however.  The 
easiest thing there would be to simply allow templated types to be 
supplied without the template parameters for specialization checking:

     class C( T : A ) {}

I haven't thought this through however so there may be problems with it.


Sean



More information about the Digitalmars-d mailing list