December 04, 2007 Re: typedefs are useless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter C. Chapin | Peter C. Chapin schrieb:
> BLS wrote:
>
>> IMO, in this case ADA is slicker than D.
>> I remember that f.i.
>> type Natural is range 0..255
>> is quit often in use.
>
> Actually that's
>
> subtype Natural is Integer range 0 .. Integer'Last;
> Peter
Thanks Peter, that's it.
Too long ago that I've used ADA. :-( However, having something similar in D would be great.
Bjoern
|
December 04, 2007 Re: typedefs are useless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter |
"Bill Baxter" wrote
> BCS wrote:
>> Steven Schveighoffer wrote:
>>> This may have arisen somewhere before, but...
>>>
>>> Let's say I want a way to create a type that's like a long, but is not implicitly convertable from a long.
>> [...]
>>
>> this is getting really close to something I have wanted for some time:
>>
>> typedef real MyReal
>> {
>> // stuff
>> }
>>
>> it would be like a struct that inherits from a primitive type. The this would be of the base type and you wouldn't be allowed to add any members. However this would allow you to do things like overload the operators. The one things in particular I would like to do would be to overload just the typing of the operators. This would result in the implementation of + (for instance) being the same as + on the underlying type, but the type of the result would be redefined. The point of this would be to allow a program to restrict the type that could be used. A concrete use case would be a SIUinits type that would, at compile time, verify unit correctness, but in the end would result in exactly the same code as if bare FP values were used.
>>
>> Thoughts?
>
> Why not just make that behavior triggered when you do
>
> struct MyReal : real
> {
> ...
> }
>
> ?
FWIW, you can do stuff like this today by using a struct with a single member of the base type you want, but you must define all the operators, but there is no implicit cast back to the base type. A struct is POD, so it occupies the same space as the single member, so you get no loss of efficiency there.
The other problem is that operators can't be used in constant expressions (which is another pet peeve I have about this). Using a typedef would allow operators to be used.
I want to say I really like BCS's idea as it really allows you to redefine all aspects of a typedef. This would be perfect for what I am trying to do.
-Steve
|
December 04, 2007 Re: typedefs are useless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer Wrote: > FWIW, you can do stuff like this today by using a struct with a single member of the base type you want, but you must define all the operators, but there is no implicit cast back to the base type. A struct is POD, so it occupies the same space as the single member, so you get no loss of efficiency there. > > The other problem is that operators can't be used in constant expressions (which is another pet peeve I have about this). Using a typedef would allow operators to be used. > > I want to say I really like BCS's idea as it really allows you to redefine all aspects of a typedef. This would be perfect for what I am trying to do. > > -Steve On Tue, 04 Dec 2007 15:38:40 +0100, Steven Schveighoffer <schveiguy@yahoo.com> wrote: > FWIW, you can do stuff like this today by using a struct with a single > member of the base type you want, but you must define all the operators, > but > there is no implicit cast back to the base type. A struct is POD, so it > occupies the same space as the single member, so you get no loss of > efficiency there. > > The other problem is that operators can't be used in constant expressions > (which is another pet peeve I have about this). Using a typedef would > allow > operators to be used. > > I want to say I really like BCS's idea as it really allows you to > redefine > all aspects of a typedef. This would be perfect for what I am trying to > do. > > -Steve Have a template, it's on the house. // start code template TypeDef(T) { T value; typeof(this) opNeg() { typeof(this) tmp; tmp.value = -this.value; return tmp; } typeof(this) opPostInc() { typeof(this) tmp; tmp.value = value++; return tmp; } typeof(this) opPostDec() { typeof(this) tmp; tmp.value = value--; return tmp; } T opCast() { return value; } static typeof(this) opCall(T rhs) { typeof(this) tmp; tmp.value = rhs; return tmp; } T opCall() // ugly hack to simulate implicit cast { return value; } typeof(this) opAdd(T rhs) { typeof(this) tmp; tmp.value = value + rhs; return tmp; } typeof(this) opSub(T rhs) { typeof(this) tmp; tmp.value = value + rhs; return tmp; } typeof(this) opMul(T rhs) { typeof(this) tmp; tmp.value = value * rhs; return tmp; } typeof(this) opDiv(T rhs) { typeof(this) tmp; tmp.value = value / rhs; return tmp; } typeof(this) opMod(T rhs) { typeof(this) tmp; tmp.value = value % rhs; return tmp; } typeof(this) opAssign(T rhs) { value = rhs; return this; } typeof(this) opAddAssign(T rhs) { value += rhs; return this; } typeof(this) opSubAssign(T rhs) { value -= rhs; return this; } typeof(this) opMulAssign(T rhs) { value *= rhs; return this; } typeof(this) opDivAssign(T rhs) { value /= rhs; return this; } typeof(this) opModAssign(T rhs) { value %= rhs; return this; } typeof(this) opAdd(typeof(this) rhs) { typeof(this) tmp; tmp.value = value + rhs.value; return tmp; } typeof(this) opSub(typeof(this) rhs) { typeof(this) tmp; tmp.value = value + rhs.value; return tmp; } typeof(this) opMul(typeof(this) rhs) { typeof(this) tmp; tmp.value = value * rhs.value; return tmp; } typeof(this) opDiv(typeof(this) rhs) { typeof(this) tmp; tmp.value = value / rhs.value; return tmp; } typeof(this) opMod(typeof(this) rhs) { typeof(this) tmp; tmp.value = value % rhs.value; return tmp; } typeof(this) opAddAssign(typeof(this) rhs) { value += rhs.value; return this; } typeof(this) opSubAssign(typeof(this) rhs) { value -= rhs.value; return this; } typeof(this) opMulAssign(typeof(this) rhs) { value *= rhs.value; return this; } typeof(this) opDivAssign(typeof(this) rhs) { value /= rhs.value; return this; } typeof(this) opModAssign(typeof(this) rhs) { value %= rhs.value; return this; } string toString() { return std.stdio.toString(value); } } // end code Used it for a quick 'n dirty test like this: // start code struct ImaginaryNumber { mixin TypeDef!(int); typeof(this) opAddAssign(int rhs){return this;} typeof(this) opSubAssign(int rhs){return this;} int opMulAssign(typeof(*this) rhs) { int result = value * rhs.value; value = 0; return -result; } typeof(this) opMulAssign(int rhs) { value *= rhs; return this; } int opMul(typeof(*this) rhs) { return -value * rhs.value; } typeof(this) opMul(int rhs) { typeof(this) tmp; tmp.value = value * rhs; return tmp; } } // end code I'd like to have a T opImplicitCastTo() {return value;} in there as well, but that will have to wait. |
December 04, 2007 Re: typedefs are useless | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | "Simen Kjaeraas" wrote
> Have a template, it's on the house.
Thank you for the code.
However, there are still 2 problems with it:
1. Every time I define a typedef of the same base type, the operators are
reinstantiated. This makes for tremendous code bloat.
2. I cannot create const versions with operators.
i.e. how do I do this:
typedef long myType;
const myType x1 = cast(myType)5;
const myType x2 = x1 * cast(myType)5;
-Steve
|
Copyright © 1999-2021 by the D Language Foundation