typedef

Denis Koroskin 2korden at gmail.com
Fri Mar 6 10:02:51 PST 2009


On Fri, 06 Mar 2009 20:47:40 +0300, Andrei Alexandrescu <SeeWebsiteForEmail at erdani.org> wrote:

> I tried typedef in two instances, to sadly conclude that it's not useful  
> as a true abstraction mechanism. The good news is that it's very close  
> to being useful.
>
> Ideally, typedef should provide a completely parallel type with the type  
> under the typedef, as if you sat down and wrote it from scratch.  
> Unfortunately, today typedef is just about equivariant with the type it  
> comes from:
>
> void main()
> {
>      typedef int IDType;
>      IDType id = 5;
>      int x = id;
> }
>
> This compiles and runs flag-free. An IDType accepts any int without any  
> fuss, and furthermore an int accepts an IDType no problem. As such,  
> typedef introduces neither a supertype nor a subtype of int.
>
> I believe this behavior is unhelpful as it prevents IDType from being a  
> true abstraction mechanism. What should happen is that only this should  
> compile:
>
> void main()
> {
>      typedef int IDType;
>      auto id = IDType(5);
>      int x = id;
> }
>
> So the literals of type IDType have the form IDType(n). That way it's  
> visible that we want to deal in IDType objects. I think it's ok that the  
> int can be be teased out of an IDType without an explicit conversion.  
> Requiring a cast would be a tad too rigid. So with the new rules in  
> place we defined a sort of subtype of int.
>
> This works even better with classes. Consider exceptions for instance:
>
> typedef Exception MyException;
>
> void main()
> {
>      try
>      {
>          throw new MyException("x");
>      }
>      catch(MyException e) { writeln("a"); }
>      catch (Exception e)  { writeln("b"); }
> }
>
> This code doesn't compile with:
>
> Error: catch at ./test.d(19) hides catch at ./test.d(20)
>
> So to the compiler typedefs are today too much the same as the source  
> type.
>
>
> Andrei

It seems that typedef defined a some kind of sub-type:

class Foo {};
typedef Foo Bar;     // a
//class Bar : Foo {} // b

void main()
{
    Bar bar;
    Foo foo;
    
    foo = bar; // fine
    bar = foo; // error
}

<OT>
Note that I get different error messages in cases a and b:
a - Error: cannot implicitly convert expression (foo) of type test.Foo to Bar
b - Error: cannot implicitly convert expression (foo) of type test.Foo to test.Bar

Is it a bug? Shoudn't the two report the same error (i.e. "test.Bar")? Does it affect mangling?
</OT>

It works the same for built-in types:

alias int Foo;
typedef Foo Bar;

void main()
{
    Bar bar;
    Foo foo;
    
    foo = bar; // fine
    bar = foo; // error
}

Looks sensible and consistent to me.




More information about the Digitalmars-d mailing list