Thread overview
Defining type coercion
Feb 27, 2011
Peter Lundgren
Feb 28, 2011
Bekenn
Feb 28, 2011
Jonathan M Davis
Feb 28, 2011
Simen kjaeraas
Feb 28, 2011
Jonathan M Davis
Feb 28, 2011
Simen kjaeraas
February 27, 2011
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.
February 28, 2011
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;
}
February 28, 2011
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
February 28, 2011
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
February 28, 2011
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
February 28, 2011
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