2011年2月14日

Delphiの特定バージョン以前/以後の判定を行う

ライブラリや共通コードを記述していると、DelphiのコンパイラやRTL/VCLの特定の機能が実装されているかどうかを判定して処理を分けたい、ということがよくあります。Delphi 2009のUnicode対応を示す標準条件シンボルの"UNICODE"のように
{$IFDEF UNICODE}
// String = UnicodeString (Delphi 2009 or later)
{$ELSE}
// String = AnsiString (Delphi 2007 or earlier)
{$ENDIF}
とできれば簡単なのですが、Windows.pasのTTokenInformationClassの新しい定義無名メソッド (ja)のサポートのように実装を示す標準条件シンボルの定義が存在しないものは単純に$IFDEFで判定できません。そこでDelphi 6で導入されたCONDITIONALEXPRESSIONSとRTLVersion/CompilerVersionを組み合わせて判定してみます。

Windows.pasにおけるTTokenInformationClassの定義はDelphi 2009(Ver20)で拡張されました。これはRTLの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
// Delphi 2-5 or 6-2007
{$ELSE}
// Delphi 2009 or later
{$IFEND}
で判定可能です(判定を逆にしたい場合はドモルガンの法則により
{$IF (DEFINED(CONDITIONALEXPRESSIONS)) AND (RTLVersion >= 20.0)}
とする)。

一方、Delphi 2010(Ver21)で言語仕様に追加されたクラスコンストラクタとクラスデストラクタについてはコンパイラの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (CompilerVersion < 21.0)}
// Class constructor/destructor is invalid
{$ELSE}
// Class constructor/destructor is valid
{$IFEND}
として判定することで、Delphi 2009およびそれ以前ではクラスコンストラクタ (ja)/クラスデストラクタ (ja)の代わりにinitialization部 (ja)/finalization部 (ja)で処理を処理を行う、といったことが可能になります。

なお$IFDEF$ENDIFで閉じますが、$IF$IFENDで閉じる、という点に注意が必要です。

0 件のコメント: