class template specialization and inheritance
Sean Kelly
sean at invisibleduck.org
Tue May 13 18:00:43 PDT 2008
== 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.
> Thanks!
> PS:
> BTW, I thought hard about the question if there is a way to do similar things in C++, that is to have a
specialization of a *class* template which is valid exactly for all classes of a given type A and all classes *derived*
from A. For function templates one can use a SFINAE-trick (the 'enable_if' template in boost) to achieve this, but I
don't see a way to do this for class templates in C++. Does anyone have an idea?
Concept checking can be done in D using the following method:
template isDerivedFromA( T ) {
const isDerivedFromA = is( T : A );
}
class C( T, bool derivedFromA : false = isDerivedFromA!(T) ) {}
class C( T, bool derivedFromA : true = isDerivedFromA!(T) ) {}
Or if a boolean isn't enough, represent the result using a type:
template getInfoOn( T ) {
static if( foo ) alias Type1 getInfoOn;
else static if( bar ) alias Type2 getInfoOn;
else alias Type3 getInfoOn;
}
class C( T, I : Type1 = getInfoOn!(T) ) {}
class C( T, I : Type2 = getInfoOn!(T) ) {}
class C( T, I : Type3 = getInfoOn!(T) ) {}
I believe a similar approach will work in C++, though you have to be a bit more clever about
implementing the concept checking code.
Sean
More information about the Digitalmars-d
mailing list