2011年11月25日金曜日

DELPHIでOverloadを使って簡単なCASTを作ってみる(2)


前回でImplicitを使ってみました。結局Implicit演算子関数のデフォルトで呼ばれる関数がどのように決まるか分りませんでした・・・(知っている方、教えてください(_ _))
なので、使われる型に関しては実装しておくのが一番ではないしょうか?
また、引数のオーバーロードも戻りのオーバーロード(のようなもの)もコンパイル時点で型のチェックがされ、実装してしまうようなので、コンパイル時点で推測できるようしないといけません。

たとえばTCastの場合次のような使い方はコンパイルエラーとなります。

Format('Integer:%d',[TCast('250')]) ; //<- "E2250 There is no overloaded version of 'Format' that can be called with these arguments"


これはコンパイル時にはTCast(...)が何を返すのか分らないからです。第一引数には%dを含んでいますが、この時点ではただの文字列です。明示的なキャストをすれば、型の推測が可能になりコンパイルできます。

Format('Integer:%d',[Integer(TCast('250'))]) ; //<- OK


TCastのソースコードを以下に示します。






unit Thorny.NumericCast;

interface
uses SysUtils;

type
  TCast = record
  private
    pS : string ;

  public
    class operator Explicit(const v : string) : TCast ; inline ;

  public
    class operator Implicit(const v : TCast) : Integer ; inline ;
    class operator Implicit(const v : TCast) : Int64 ; inline ;
    class operator Implicit(const v : TCast) : Extended ; inline  ;
    class operator Implicit(const v : TCast) : Double ; inline  ;
    class operator Implicit(const v : TCast) : Single ; inline  ;

    function TryTo(var v : Integer) : Boolean ; overload ;
    function TryTo(var v : Int64) : Boolean ; overload ;
    function TryTo(var v : Extended) : Boolean ; overload ;
    function TryTo(var v : Double) : Boolean ; overload ;
    function TryTo(var v : Single) : Boolean ; overload ;
  end;


implementation


{ TCast }

class operator TCast.Explicit(const v: string): TCast;
begin
  result.pS := v ;
end;

class operator TCast.Implicit(const v: TCast): Extended;
begin
  result := StrToFloat(v.pS) ;
end;

class operator TCast.Implicit(const v: TCast): Integer;
begin
  result := StrToInt(v.pS) ;
end;

class operator TCast.Implicit(const v: TCast): Double;
begin
  result := StrToFloat(v.pS) ;
end;


class operator TCast.Implicit(const v: TCast): Single;
begin
  result := StrToFloat(v.pS) ;
end;

class operator TCast.Implicit(const v: TCast): Int64;
begin
  result := StrToInt64(v.pS) ;
end;

function TCast.TryTo(var v: Single): Boolean;
begin
  result := TryStrToFloat(pS,v) ;
end;

function TCast.TryTo(var v: Int64): Boolean;
begin
  result := TryStrToInt64(pS,v) ;
end;

function TCast.TryTo(var v: Integer): Boolean;
begin
  result := TryStrToInt(pS,v) ;
end;

function TCast.TryTo(var v: Extended): Boolean;
begin
  result := TryStrToFloat(pS,v) ;
end;

function TCast.TryTo(var v: Double): Boolean;
begin
  result := TryStrToFloat(pS,v) ;
end;

end.

TryTo関数を追加してみました。これは見てわかるようにTryStrTo...関数を呼んでいるだけです(汗)。 varを付けた引数の場合、型が一致している必要があるようです。共変性などあるといいと思うのですが。

 ソースコードは自由にご使用ください。ただし問題が起きても責任はとれません。

0 件のコメント:

コメントを投稿