Just to keep the pot boiling.
Regrettably, all of the assignments etc. below work:
type
TMeters= type double;
TKilometers= type double;
TFeet= type integer;
...
procedure testTypeCompatibility;
const
meters: TMeters= 1.0;
kilometers: TKilometers= 1.0;
var
m: TMeters;
k: TKilometers;
d: double;
procedure pM(m: TMeters);
begin
end { pM } ;
begin
m := kilometers; (* Should fail *)
m := meters; (* Should be OK *)
k := meters; (* Should fail *)
k := kilometers; (* Should be OK *)
d := meters; (* Should fail *)
d := kilometers; (* Should fail *)
d := m; (* Should fail *)
m := d; (* Should fail *)
k := d; (* Should fail *)
pM(meters); (* Should be OK *)
pM(m); (* Should be OK *)
pM(kilometers); (* Should fail *)
pM(k); (* Should fail *)
pM(d) (* Should fail *)
end { testTypeCompatibility } ;
If TMetres etc. were actually defined as records with a single field, could that field be set to be the default (i.e. accessed implicitly if not specified)?
...OTOH that probably wouldn't help because implicit access to the value (i.e. a double whatever) would hide the distinct type of the record :-(
I think I asked this elsewhere in the context of Delphi ten years or so ago, because I was musing about the capabilities of a C++ toolkit which could actually flag dimensionality errors (i.e. assigning seconds to meters etc.) as a compilation error. I was given a workaround, but it was subtle and might have relied on RTTI etc... not sure whether I can find it, and not sure whether it's worth the effort.
I could possibly justify heavy modification of the code to encode distances as a record including both a value and a datum, but that's not going to happen immediately. Tightening up all functions etc. to use a TMetres or TFeet rather than just a double or integer would be a good start.
I've not actually seen a screwed assignment, but this started when I realised that I was outputting something as feet when it was still actually in meters: which is of course a whole other can of worms.
MarkMLl