Type polymorphism and type variance

Ali Çehreli acehreli at yahoo.com
Wed Dec 5 10:51:07 PST 2012


On 12/05/2012 04:28 AM, Lubos Pintes wrote:

 > where is the value of concrete T?
 > Or perhaps I completely misunderstood this?

Maybe I misunderstand you. :) Are you pointing out that the class 
template that I have shown did not have any member variables? If so, 
they can have anything they want.

I have changed the program to include different members and even 
specialization (for dchar):

import std.stdio;

/* This defines what I want to do with my objects: */
interface MyInterface
{
     void foo();

     /* This is just a silly function to demonstrate that copying an object
      * must be the responsibility of that object because we do not know the
      * concerete type at this level. */
     MyInterface dup();
}

/* A class template that implements the interface */
class myGtype(T)
     if (!is(T == dchar))
   : MyInterface
{
     /* Here is a concrete value: */
     T value;

     /* The implementation can be arbitrarily complex for different T: */
     static if (is (T == S)) {
         S[string] aa;
     }

     this(T value)
     {
         this.value = value;

         static if (is (T == S)) {
             aa["hello"] = value;
         }
     }

     void foo()
     {
         /* This demonstrates how operations that depend on T can be used
          * inside this class template.
          *
          * specialOperationFor() could alternatively be a member function
          * template but I find it simpler when it is a free-standing 
function.
          */
         specialOperationFor!T(value);
     }

     /* This one simply uses 'value'. It could do anything else. */
     myGtype dup()
     {
         return new myGtype(value);
     }
}

/* It is possible to implement a specialization of the type completely
  * separately: */
class myGtype(T)
     if (is(T == dchar))
     : MyInterface
{
     void foo()
     {
         writeln("Inside myGtype!dchar.foo");
     }

     myGtype dup()
     {
         return new myGtype();
     }
}

void specialOperationFor(T : double)(double d)
{
     writefln("Special operation for double: %s", d);
}

struct S
{
     int i;
}

void specialOperationFor(T : S)(S s)
{
     writefln("Special operation for S: %s", s);
}

void main()
{
     MyInterface[] objects;

     objects ~= new myGtype!double(1.5);
     objects ~= new myGtype!int(42);
     objects ~= new myGtype!S(S(100));
     objects ~= new myGtype!dchar();

     foreach (o; objects) {
         o.foo();
     }

     // We can even copy them and the copies have the correct types:
     foreach (i, o; objects) {
         auto c = o.dup();
         writefln("Using the copy of item %s", i);
         c.foo();
     }
}

Ali



More information about the Digitalmars-d-learn mailing list