Delphi – How to use the overload operator to assign empty set to record

I am using records to encapsulate two exception sets.
I have put in operators to allow either group to be assigned to records. Doing so will clear the other. < br>But I cannot specify an empty set.

Please refer to the following sample code:

Program test;

{$Apptype console}
type
TSomeThing = (a,b,c);
TOtherThing = (x,y,z);
TSomeThings = set of TSomething;< br /> 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:= [];
e nd.

[dcc64 Error] InstructionList.pas(512): E2010 Incompatible types:’TSomeRecord’ and’Set’

How do I do this Can I assign empty sets to my records?
I can abuse the implicit operator to allow SomeRec:= nil;, but this looks very ugly.

The compiler cannot tell whether you are referring to an empty set of TSomeThing or an empty set of TOtherThing. You can declare typed constants to allow the compiler to resolve overloading:

const
EmptySomeThings: TSomeThings = [];
EmptyOtherThings: TOtherThings = [];

Then compile and resolve the following assignments as you expect:

SomeRec:= EmptySomeThings;
SomeRec:= EmptyOtherThings;

Of course, you know that any of them has the same effect because of the implementation of the Implicit operator One field is set, and another field is cleared. But the compiler cannot know this.

If you want to clear the two members of the record, you can always use:

< /p>

SomeRec:= Default(TSomeRecord);

Personally, I might wrap it in such a static class method:

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 It is possible to declare a constant in the type, but the language designer did not think of this, and unfortunately it is impossible.

Update

Rudy correctly pointed out in the comments, Constants can be added to the record type through the record assistant. This is news to me because I mistakenly think that the assistant can only add methods. This is what I like about Sta ck Overflow. Even if you think you know well, you can always get more knowledge. Thank you Rudy.

So you can write:

< pre>type
TSomeRecordHelper = record helper for TSomeRecord
public
const
Default: TSomeRecord = ();
end;

I am using records to encapsulate two exception sets.
I have put in operators to allow either group to be assigned to records. Doing so will clear the other group.
But I cannot specify An empty set.

Please refer to the following sample 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;
< br />var
SomeRec: TSomeRecord;

begin
SomeRec:= [];
end.

[dcc64 Error ] InstructionList.pas(512): E2010 Incompatible types:’TSomeRecord’ and’Set’

How can I do it so that I can assign an empty set to my record?
I can abuse the implicit operator to allow SomeRec:= nil;, but this looks very ugly.

The compiler can’t tell what you mean An empty set of TSomeThing is still an empty set of TOtherThing. You can declare typed constants to allow the compiler to resolve overloading:

const
EmptySomeThings: TSomeThings = [];
EmptyOtherThings: TOtherThings = [];

Then compile and resolve the following assignments according to your expectations:

SomeRec: = EmptySomeThings;
SomeRec:= EmptyOtherThings;

Of course, you know that any of them has the same effect because the implementation of the Implicit operator sets one field and clears the other. But the compiler cannot know this.

If you want to clear the two members of the record, you can always use:

SomeRec:= Default(TSomeRecord );

Personally, I might wrap it 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 can declare a constant in the type, but the language designer Did not expect this, and unfortunately it is impossible.

Update

Rudy correctly pointed out in the comments that constants can be added to the record type through the record helper. This It’s news to me because I mistakenly think that assistants can only add methods. This is what I like Stack Overflow. Even if you think you know well, you can always get more knowledge. Thank you Rudy. < /p>

So you can write:

type
TSomeRecordHelper = record helper for TSomeRecord
public
const
Default: TSomeRecord = ();
end;

Leave a Comment

Your email address will not be published.