typedef: what's it good for?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Nov 11 08:54:27 PST 2009


Walter Bright wrote:
> When I originally worked out ideas for D, there were many requests from 
> the C and C++ community for a 'strong' typedef, and so I put one in D. I 
> didn't think about it too much, just assumed that it was a good idea.
> 
> Now I'm not so sure. Maybe it should be removed for D2.
> 
> Does anyone use typedef's?
> 
> What do you use them for?
> 
> Do you need them?

One good way to figure out how well-defined something is would be to 
attempt explaining it to someone. That's what happened as I was writing 
about typedef in TDPL. I realized the following:

* typedef is hopelessly broken in very many ways

* nobody noticed (i.e. no bugzilla reports), so probably nobody uses it

* fixing it to do anything remotely useful would be a major effort and 
would complicate the language

* even if fixed to do something useful, the usefulness would be very limited

* it's unclear which of two different fixes would make it more useful 
and less confusing

The last point was revealed by a conversation between Walter and me last 
night. I pointed out that typedef should create a *subtype* of a type, e.g.:

typedef int ID;
ID id;
int x;
id = x; // no
x = id; // yes

He pointed out that typedef should create a *supertype*, e.g.:

typedef int ID;
ID id;
int x;
id = x; // yes
x = id; // no

I still think that subtype would be a better choice than supertype, but 
I also could see cases in which you want the supertype case. So I expect 
that whatever we choose, some may expect the opposite and get confused.

One alternative is to make typedef a completely separate type, with 
explicit casts:

typedef int ID;
ID id;
int x;
id = x;      // no
x = id;      // no
id = ID(x);  // yes
x = int(id); // yes

Then everybody would complain that the "right" direction is not implicit.

Subtype vs. supertype is only the beginning of problems. Consider some 
choice has been made, and then look at this orthogonal problem:

struct A {
    A foo();
    void bar(A);
    A baz(A);
}
typedef A B;

What should that do? After much thinking, I concluded the most 
reasonable thing it could do is to replace A with B throughout the 
definition, e.g.:

struct B {
    B foo();
    void bar(B);
    B baz(B);
}

I found some examples for the usefulness of that, but then also examples 
in which some or all of those functions should use an A sometimes.

Today, typedef does essentially nothing notable or even correct and 
consistent for structs, classes, pointers, and arrays. It even has some 
egregious errors, for example when defining binary operators. Nobody 
noticed them probably because nobody used them.

Walter's and my interim conclusion last night was that fixing typedef 
would be difficult, and that the usefulness of typedef is too little for 
its complexity. It may be a good idea to just remove it from the 
language. We already have a host of other abstraction-building 
mechanisms, and typedef does not seem to build a good abstraction.


Andrei



More information about the Digitalmars-d mailing list