typedef int: adding operators? (opAdd, etc.)

Charles D Hixson charleshixsn at earthlink.net
Tue Apr 3 23:06:59 PDT 2007


BCS wrote:
> Reply to Charles,
> 
>> Is there any way to add operators defined on a type which is defined
>> off of the built-in types?
>>
>> In particular, it would be nice, e.g., to be able to define types for
>> byteNo, wordNo, etc., and be able to add them together (where, say,
>> one word == 4 bytes).
>>
>> Currently I'm doing this kind of thing on an ad hoc basis, but that
>> means that type information is spread out all over the place, and it
>> would be nice to concentrate it in one place. (In one instance I'm
>> converting between record ID's and disk addresses.  It's easy enough
>> to do, but if I change the record size I'll need to track down each
>> place where I cast from one type to another.  Not optimal.)
>>
>> I suppose I could just write a special function for each conversion,
>> and stick them all in the same place, and I may do just that, but this
>> approach strikes me as less than ideal.
>>
>> I suppose defining:
>> ByteNo opAdd(ByteNo b, WordNo w) { ... }
>> and then calling it via:
>> ByteNo b1 = opAdd(b0, w0);
>> isn't horrendous, but it's not as nice as
>> ByteNo b1 = b0 + w0;
> 
> somewhere there is a compile time units lib that does much of this kind 
> of thing. It wraps the internal real type in a struct and forces the 
> conventions to get to it. It might not be quite what you want because it 
> would convert everything to the same type internally (bytes in your 
> case) and you'd pay a price any time you use it as something else. You 
> might take a look anyway.
> 
> 
Sorry, that's a reasonable idea, but it's *NOT* what I want. 
This was just one example of a large number of cases.  It's 
because I have a tendency to use specialized types for error 
checking.  So I'll have (e.g.) an inches type, and a kilograms 
type, and then, LATER, I'll add a centimeters type.  O! but 
centimeters are smaller than inches...and they don't convert 
evenly.  So if I store the distances in centimeters, the 
result in inches will always be off...and everything I've 
stored previously will need to be reconverted.  (N.B.:  These 
are just examples.  Things I can use without explaining.)  But 
I don't want to do the conversions until they time when I need to.

And what I generally really want to do is either operate with 
a literal number (e.g., 5), or call a library routine without 
a lot of extraneous casts...which are each a point of failure 
if I later redesign some part.

(In the particular case in question I KNOW I'm going to 
redesign later.  One of the units is record # and another is 
disk address.  It currently depends on fixed length records, 
but it's going to be redesigned to accept records of varying 
length.  But not yet.  So I've got types like:
typeof uint RecordNo;
typeof uint DiskAddr;
Everything's fine, as long as I remember to put in all of the 
casts...but later things will get more complex, and already 
I've got expressions with casts of casts where I'm doing 
something like:
RecordNo newRec = cast(RecordNo)(1 + (cast(uint)diskLoc - 
headerSize ) / recSize);
That's not exactly one of them,..but it should give you a flavor.

A part of the reason that things are being done the way that 
they are is "It's a translation from C++".  I'm sure that 
there are better ways, and once I understand what I'm doing 
I'll figure some of them out.  For now, I'd just like the code 
to be clean enough not to cause problems later.  And I guess 
that means lots of functions like:
DiskAddress rn2da(RecordNo r) { ... }

Ugly, but better than lots of casts all over everywhere.  And 
easy to recognize when you're trying to figure out again "Just 
what's happening HERE?"



More information about the Digitalmars-d-learn mailing list