I'm using a record to encapsulate two dissimular sets.
I've put in operators to allow the assignment of either set to the record. Doing so will clear the other set.
However I cannot assign an empty set.
See the following example code:
Program test;
{$Apptype console}
type
TSomeThing = (a,b,c);
TOtherThing = (x,y,z);
TSomeThings = set of TSomething;
TOtherThings = set of TOtherThing;
TSomeRecord = record
strict private
Fa: TSomeThings;
Fb: TOtherThings;
public
class operator Implicit(a: TSomeThings): TSomeRecord;
class operator Implicit(a: TOtherThings): TSomeRecord;
end;
implementation
class operator TSomeRecord.Implicit(a: TSomeThings): TSomeRecord;
begin
Result.Fa:= a;
Result.Fb:= [];
end;
class operator TSomeRecord.Implicit(a: TOtherThings): TSomeRecord;
begin
Result.Fa:= [];
Result.Fb:= a;
end;
var
SomeRec: TSomeRecord;
begin
SomeRec:= [];
end.
[dcc64 Error] InstructionList.pas(512): E2010 Incompatible types: 'TSomeRecord' and 'Set'
How do I make it so I can assign the empty set to my record?
I can misuse the implicit operator to allow SomeRec:= nil;, but that looks very ugly.
The compiler cannot tell whether you mean an empty set of TSomeThing or an empty set of TOtherThing. You can declare typed constants to allow the compiler to resolve the overload:
const
EmptySomeThings: TSomeThings = [];
EmptyOtherThings: TOtherThings = [];
Then the following assignments compile and resolve as you would expect:
SomeRec:= EmptySomeThings;
SomeRec:= EmptyOtherThings;
Of course, you know that either one of these has the same effect, because the implementation of the Implicit operators sets one field, and clears the other. But the compiler cannot know this.
If you wish to clear both members of the record you can always use:
SomeRec:= Default(TSomeRecord);
I personally might wrap that up in a static class method like this:
class function Default: TSomeRecord; static;
....
class function TSomeRecord.Default: TSomeRecord;
begin
Result := Default(TSomeRecord);
end;
Then you can write:
SomeRec:= TSomeRecord.Default;
In an ideal world you'd be able to declare a constant in the type, but the language designers did not think of that and it is sadly not possible.
Update
Rudy correctly points out in a comment, that constants can be added to a record type by way of a record helper. This was news to me as I mistakenly believed that helpers could only add methods. This is what I love about Stack Overflow. Even when you think you know something pretty well, there's always scope for more knowledge to be acquired. Thanks Rudy.
So you might write:
type
TSomeRecordHelper = record helper for TSomeRecord
public
const
Default: TSomeRecord = ();
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With