Use operator overloading for classes with non-ARC compiler
はじめに
演算子オーバーロードはDelphi 2006で導入された機能で、自分が定義したレコードに+や-といった演算子の動作を実装できます。この機能はARC対応コンパイラであればレコードだけでなくクラスでも使えるんですが、非ARCコンパイラ、つまりx86向けのようなコンパイラでは使うことができませんでした。
ところが何気なくコードを書いていたところ、ちょっと違う書き方をするだけで演算子オーバーロードがクラスでも使えることを発見しました。また、同じ記述方法でクラスヘルパーやレコードヘルパーで演算子オーバーロードを後付けするという従来では完全に不可能だったことまでできるようになり、コーディングの幅が広がる可能性があります。
使い方
https://gist.github.com/lynatan/886ed984d230ac1b42dd89ed42ab2214
type TStringListEx = class(TStringList) public // class operator In(const A: string; B: TStringListEx): Boolean; class function &&op_In(const A: string; B: TStringListEx): Boolean; static; end; TPointHelper = record helper for TPoint // Possible in class helper! public // class operator Equal(const A: TPoint; const B: string) : Boolean; class function &&op_Equality(const A: TPoint; const B: string): Boolean; static; end; class function TStringListEx.&&op_In(const A: string; B: TStringListEx): Boolean; begin Result := B.IndexOf(A) >= 0; end; class function TPointHelper.&&op_Equality(const A: TPoint; const B: string): Boolean; begin Result := Format('%d,%d', [A.X, A.Y]) = B; end; var sl: TStringListEx; pt: TPoint; ret: Boolean; begin sl := TStringListEx.Create; sl.Add('AAA'); sl.Add('BBB'); ret := 'AAA' in sl; Writeln(BoolToStr(ret, True)); // -> 'True' pt := Point(123, 456); ret := pt = '123,456'; Writeln(BoolToStr(ret, True)); // -> 'True' ... end;
対応表
| class operator | class function |
|---|---|
| Implicit | &&op_Implicit |
| Explicit | &&op_Explicit |
| Negative | &&op_UnaryNegation |
| Positive | &&op_UnaryPlus |
| Inc | &&op_Increment |
| Dec | &&op_Decrement |
| LogicalNot | &&op_LogicalNot |
| Trunc | &&op_Trunc |
| Round | &&op_Round |
| In | &&op_In |
| Equal | &&op_Equality |
| NotEqual | &&op_Inequality |
| GreaterThan | &&op_GreaterThan |
| GreaterThanOrEqual | &&op_GreaterThanOrEqual |
| LessThan | &&op_LessThan |
| LessThanOrEqual | &&op_LessThanOrEqual |
| Add | &&op_Addition |
| Subtract | &&op_Subtraction |
| Multiply | &&op_Multiply |
| Divide | &&op_Division |
| IntDivide | &&op_IntDivide |
| Modulus | &&op_Modulus |
| LeftShift | &&op_LeftShift |
| RightShift | &&op_RightShift |
| LogicalAnd | &&op_LogicalAnd |
| LogicalOr | &&op_LogicalOr |
| LogicalXor | &&op_ExclusiveOr |
| BitwiseAnd | &&op_BitwiseAnd |
| BitwiseOr | &&op_BitwiseOr |
| BitwiseXor | &&op_BitwiseXOR |
| Include | &&op_Include |
| Exclude | &&op_Exclude |