[   ^ to index...   |   <-- previous   |   next -->   ]

C++ templates vs. ML polymorphism

Last week, I said there was a tension between expressiveness and safety. Permissive types allow more programs to be written; restrictive types allows stricter reasoning about programs. We see this tension when we compare parametric polymorphism in C++ and ML.

C++ templates are extremely permissive. Here's the C++ equivalent of ML's 'a list:

template <class T>
class ListNode {
private:
    T* hd;
    ListNode* tl;
public:
    ListNode(T * head, ListNode * tail) : hd(head), tl(tail) {}
    T* head() { return hd; }
    ListNode* tail() { return tl; }
};

ListNode<int> * nums
    = new ListNode<int>(new int(10), new ListNode<int>(new int(30), NULL));

C++ instantiates templates using a process that is essentially textual substitution. When you use the type ListNode<int>, the compiler automatically generates the following class:

class ListNode__int__ {
private:
    int* hd;
    ListNode__int__* tl;
public:
    ListNode__int__(int * head, ListNode__int__ * tail) : hd(head), tl(tail) {}
    int* head() { return hd; }
    ListNode__int__* tail() { return tl; }
};

Obviously, the client code needs to be changed as well:

ListNode__int__ * nums
    = new ListNode__int__(new int(10), new ListNode__int__(new int(30), NULL));

The names of these template instantiations will be mangled by the compiler, so as not to conflict with any programmer-defined classes.

It is also possible to define template functions. Here's the function length over lists:

template <class List>
int length(List * list)
{
    if (list == NULL) {
        return 0;
    } else {
        return 1 + length(list->tail());
    }
}

cout << length< ListNode<int> >(nums); // USAGE


Keunwoo Lee
Last modified: Wed Apr 11 22:49:15 PDT 2001