digitalmars.D - typedef
- Andrei Alexandrescu (45/45) Mar 06 2009 I tried typedef in two instances, to sadly conclude that it's not useful...
- Denis Koroskin (31/77) Mar 06 2009 It seems that typedef defined a some kind of sub-type:
- Tim M (16/62) Mar 06 2009 I've never really found typedefs of any use. You say it makes it clearer...
- Andrei Alexandrescu (19/46) Mar 06 2009 Well I was wondering whether others have success stories about typedef
- Tim M (8/47) Mar 06 2009 Derelict uses typedef for functions and alias for others by convention:
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
Mar 06 2009
On Fri, 06 Mar 2009 20:47:40 +0300, Andrei Alexandrescu <SeeWebsiteForEmail 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. AndreiIt 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.
Mar 06 2009
On Sat, 07 Mar 2009 06:47:40 +1300, Andrei Alexandrescu <SeeWebsiteForEmail 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. AndreiI've never really found typedefs of any use. You say it makes it clearer that you are dealing with IDType objects. But they are not objects. If you had used objects you could have defined the constuctor to get the syntax you are looking for because taking away this syntax: IDType id = 5; Should also remove the following syntaxes to keep D simple: *= += -+ %= etc.. So you end up with a type that stores int data but cant be used for arithmetic. What good would that be keeping in mind that D already has enums?
Mar 06 2009
Tim M wrote:On Sat, 07 Mar 2009 06:47:40 +1300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Well I was wondering whether others have success stories about typedef to share. Here's an example that would have made it very handy for me to use a good typedef. I have a machine translation app that deals with sentences in two languages. Furthermore, in the target language there are several hypotheses per sentence. I undergo intensive manipulation of these things, and found bugs because I confuse e.g. the IDs of sentences in different languages. So I index in a hash for one language with an ID from another language, which is a bug. So I though, alright, let me typedef IDs so they never mix up: typedef uint SourceSntID; typedef uint TargetSntID; typedef uint HypothesisID; Things did improve considerably but I found it annoying that these IDs, which are supposed to be essentially independent types, convert to and from uint at the drop of a hat. I could define structs for them but that's onerous - like dozens of lines instead of one line. AndreiI 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.I've never really found typedefs of any use. You say it makes it clearer that you are dealing with IDType objects. But they are not objects. If you had used objects you could have defined the constuctor to get the syntax you are looking for because taking away this syntax: IDType id = 5; Should also remove the following syntaxes to keep D simple: *= += -+ %= etc.. So you end up with a type that stores int data but cant be used for arithmetic. What good would that be keeping in mind that D already has enums?
Mar 06 2009
On Sat, 07 Mar 2009 17:04:56 +1300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Tim M wrote:Derelict uses typedef for functions and alias for others by convention: "The declarations of the function pointers should be typedefed and should have the following syntax:" http://svn.dsource.org/projects/derelict/trunk/docs/derelictify.html It seems to be in strong use for where an alias could do the job just fine: http://www.google.com/search?rls=en&rls=en&q=site:dsource.org+typedef&sourceid=opera&ie=utf-8&oe=utf-8On Sat, 07 Mar 2009 06:47:40 +1300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Well I was wondering whether others have success stories about typedef to share. Here's an example that would have made it very handy for me to use a good typedef. I have a machine translation app that deals with sentences in two languages. Furthermore, in the target language there are several hypotheses per sentence. I undergo intensive manipulation of these things, and found bugs because I confuse e.g. the IDs of sentences in different languages. So I index in a hash for one language with an ID from another language, which is a bug. So I though, alright, let me typedef IDs so they never mix up: typedef uint SourceSntID; typedef uint TargetSntID; typedef uint HypothesisID; Things did improve considerably but I found it annoying that these IDs, which are supposed to be essentially independent types, convert to and from uint at the drop of a hat. I could define structs for them but that's onerous - like dozens of lines instead of one line. AndreiI 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.I've never really found typedefs of any use. You say it makes it clearer that you are dealing with IDType objects. But they are not objects. If you had used objects you could have defined the constuctor to get the syntax you are looking for because taking away this syntax: IDType id = 5; Should also remove the following syntaxes to keep D simple: *= += -+ %= etc.. So you end up with a type that stores int data but cant be used for arithmetic. What good would that be keeping in mind that D already has enums?
Mar 06 2009