www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Defining type coercion

reply Peter Lundgren <lundgrpb rose-hulman.edu> writes:
I'd like to define a type Ordinal which behaves like an int (using a struct or
alias) that represents the 26 letters, A-Z, with the numbers 1-26. Then, I
would like to be able to coerce between chars and Ordinals appropriately.

chars and ints already have the ability to coerce between each other using the
appropriate ASCII values. So, really, I'd just like to define a type that
overrides this behavior.

As far as I can tell, the place to define such rules is with opCast!, but I'm
at a loss for how to add additional rules to built in types.
Feb 27 2011
next sibling parent Bekenn <leaveme alone.com> writes:
On 2/27/2011 12:10 PM, Peter Lundgren wrote:
 I'd like to define a type Ordinal which behaves like an int (using a struct or
 alias) that represents the 26 letters, A-Z, with the numbers 1-26. Then, I
 would like to be able to coerce between chars and Ordinals appropriately.

 chars and ints already have the ability to coerce between each other using the
 appropriate ASCII values. So, really, I'd just like to define a type that
 overrides this behavior.

 As far as I can tell, the place to define such rules is with opCast!, but I'm
 at a loss for how to add additional rules to built in types.

I haven't tried anything like this yet (I'm still pretty new to D), but I think something like this is the best you'll be able to do: struct Ordinal { this(int value) { m_Value = value; } this(dchar ch) { m_Value = ch - 'a' + 1; } // add range checks as appropriate alias this m_Value; T opCast(T)() if (T is dchar) { return m_Value + 'a' - 1; } // add more operators as appropriate private: int m_Value; }
Feb 27 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 27 February 2011 12:10:43 Peter Lundgren wrote:
 I'd like to define a type Ordinal which behaves like an int (using a struct
 or alias) that represents the 26 letters, A-Z, with the numbers 1-26.
 Then, I would like to be able to coerce between chars and Ordinals
 appropriately.
 
 chars and ints already have the ability to coerce between each other using
 the appropriate ASCII values. So, really, I'd just like to define a type
 that overrides this behavior.
 
 As far as I can tell, the place to define such rules is with opCast!, but
 I'm at a loss for how to add additional rules to built in types.

You can use opCast, but it's only for _explicit_ casting. You can use alias this for implicit casting, but that's not going to work very well with primitive types, because you can't derive from them and therefore can't override their behavior. Also, you can't currently have more than one alias this per type (though you're supposed to be able to eventually). So, you could easily create a type which holds an integral value of some kind and only allows the values 1 - 26, inclusive. You can make it so that functions on it take ints or chars or whatever. You can define opCast to cast to whatever types you want. But you _can't_ make it implicitly convertible to or from primitive types and have _any_ control over the conversion (since alias this with a primitive type gives you no control over it). But then again, you can't convert implicitly between chars and ints either unless value range propogation tells the compiler that the conversion that you're trying to do will fit, and that's generally restricted to literals in local context. As soon as you do anything like pass a variable to function, that information is lost and you're going to have to cast explicitly. So, while you _can_ implicitly cast from a char to an int, you can't generally do so from an int to a char, so your type would be just as implicitly castable as chars and ints except that you wouldn't be able to cast from it to an int implicitly. D really isn't designed with allowing you to define a type which acts like other types without casts (unless you're dealing with polymorphism). C++ allows all kinds of implicit conversions that D explicitly disallows in order to avoid bugs. - Jonathan M Davis
Feb 27 2011
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Peter Lundgren <lundgrpb rose-hulman.edu> wrote:

 I'd like to define a type Ordinal which behaves like an int (using a  
 struct or
 alias) that represents the 26 letters, A-Z, with the numbers 1-26. Then,  
 I
 would like to be able to coerce between chars and Ordinals appropriately.

 chars and ints already have the ability to coerce between each other  
 using the
 appropriate ASCII values. So, really, I'd just like to define a type that
 overrides this behavior.

 As far as I can tell, the place to define such rules is with opCast!,  
 but I'm
 at a loss for how to add additional rules to built in types.

The D Programming Language (the book by Andrei) mentions that multiple alias this be a possibility. Sadly, it has not yet found its way its way into the actual implementation of the language. With it, one would define what you ask for, approximately like this: struct Ordinal { private int representation; char getChar( ) { return representation + 'a'-1; } alias representation this; alias getChar this; } But like I said, it currently does not work. -- Simen
Feb 27 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 27 February 2011 21:57:26 Simen kjaeraas wrote:
 Peter Lundgren <lundgrpb rose-hulman.edu> wrote:
 I'd like to define a type Ordinal which behaves like an int (using a
 struct or
 alias) that represents the 26 letters, A-Z, with the numbers 1-26. Then,
 I
 would like to be able to coerce between chars and Ordinals appropriately.
 
 chars and ints already have the ability to coerce between each other
 using the
 appropriate ASCII values. So, really, I'd just like to define a type that
 overrides this behavior.
 
 As far as I can tell, the place to define such rules is with opCast!,
 but I'm
 at a loss for how to add additional rules to built in types.

The D Programming Language (the book by Andrei) mentions that multiple alias this be a possibility. Sadly, it has not yet found its way its way into the actual implementation of the language. With it, one would define what you ask for, approximately like this: struct Ordinal { private int representation; char getChar( ) { return representation + 'a'-1; } alias representation this; alias getChar this; } But like I said, it currently does not work.

Would "alias getChar this" really be legal? I thought that this had to be aliased to a type. - Jonathan M Davis
Feb 27 2011
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Jonathan M Davis <jmdavisProg gmx.com> wrote:

 struct Ordinal {
      private int representation;
      char getChar( ) {
          return representation + 'a'-1;
      }
      alias representation this;
      alias getChar this;
 }

 But like I said, it currently does not work.

Would "alias getChar this" really be legal? I thought that this had to be aliased to a type.

Alias function this; works. -- Simen
Feb 28 2011