docwikiでは教えてくれない演算子オーバーロード。
In演算子
Inをオーバーロードすると、集合演算子としてのinの動作を定義できるようになる*1。
// サンプル type TStrRec = record public Value: TArray<string>; class operator In(const A: string; const B: TStrRec): Boolean; end; class operator TStrRec.In(const A: string; const B: TStrRec): Boolean; var s: string; begin for s in B.Value do if s = A then Exit(True); Result := False; end; // 使い方 var str: TStrRec; begin str.Value := TArray<string>.Create('わはー', '!'); if 'ほげ' in str then Writeln('あった'); // 条件がFalseとなり実行されない if 'わはー' in str then Writeln('あった'); // 条件がTrueとなり実行される end;
IncludeとExclude手続き
これも集合を操作するInclude及びExlude手続きのオーバーロード。元々これらの手続きはあってもあまり使わないから*2、オーバーロード時には何か別の目的を持たせないとそのままでは使い道がなさそう。
// サンプル type TFoobar = (foo, bar, baz); TIncludeExclude = record Value: set of TFoobar; class operator Include(a: TIncludeExclude; b: TFoobar): TIncludeExclude; class operator Exclude(a: TIncludeExclude; b: TFoobar): TIncludeExclude; end; class operator TIncludeExclude.Include(a: TIncludeExclude; b: TFoobar): TIncludeExclude; begin Result := a; Include(Result.Value, b); end; class operator TIncludeExclude.Exclude(a: TIncludeExclude; b: TFoobar): TIncludeExclude; begin Result := a; Exclude(Result.Value, b); end; // 使い方 var ie: TIncludeExclude; begin ie.Value := []; Include(ie, foo); Include(ie, baz); Exclude(ie, foo); Include(ie, bar); end;
TrueとFalse
Trueをオーバーロードすると、論理値として使えるようになる。
// サンプル type TBoolean = record Value: Integer; class operator True(a: TBoolean): Boolean; end; class operator TBoolean.True(a: TBoolean): Boolean; begin Result := a.Value <> 0; end; // 使い方 var b: TBoolean; begin b.Value := 0; if b then Writeln('True'); // 条件がFalseとなり実行されない b.Value := 1; if b then Writeln('True'); // 条件がTrueとなり実行される end;
ただ、Falseの方は用途が不明。Falseのみ、あるいはTrueとFalse両方をオーバーロードした場合を試したけど、どちらもFalse側の処理は呼ばれなかった。あと、if not b thenとするとLogicalNotを見に行くのか、「この型には指定した演算子は使えません」というエラーが出た。
OnesComplement演算子
これは名前から分かるようにビット反転用と思われるが、書いても動かなかった。そもそもビット反転にはBitwiseNotがすでにあること、及びこれと上記のFalseがうまく動作しないことから考えると、C++Builder用のものか?*3
見つけた経緯
例えばTStringListで中に特定の文字列が含まれてるか知りたいとき、
var sl: TStringList; begin if sl.IndexOf('わはー') <> -1 then ... end;
じゃなくて、
var sl: TStringList; begin if 'わはー' in sl then ... end;
みたいに書けたら楽だなーとか思ってて、何気なくbinフォルダの中身に'GreaterThanOrEqual'*4でbgrepしたら見つけた的な。
ちなみに
ググってみたところ当たり前ながらすでに発見してた人はいたみたい。
https://forums.embarcadero.com/thread.jspa?messageID=197242&tstart=0