2010年12月9日

CONDITIONALEXPRESSIONS

CONDITIONALEXPRESSIONSはVER140(Delphi 6, C++Builder 6, Kylix 1/2/3)以降で使用可能な標準条件シンボルで、$IFに対して値に関する条件を記述できることを示しています(CONDITIONALEXPRESSIONSが未定義なら$IFDEF/$IFNDEFで条件シンボルが定義されているかどうかの判定しかできませんが、定義されていれば値を"="、"<"、"<="、">"、">="、"<>"で比較できます)。

このときに使用できるRTLVersion/CompilerVersion/FireMonkeyVersionは定数で、RTLVersion(System.pasで定義)はVER140以降で使用可能、CompilerVersion(コンパイラがSystem.pasをコンパイルするときに設定)はVER140以降のKylix 1以外で使用可能、FireMonkeyVersion(FMX.Types.pasで定義)はDelphi XE2 Update 2以降のFireMonkeyアプリケーションで使用可能です。

各バージョンにおけるRTLVersion、CompilerVersion、FireMonkeyVersionの値は以下のようになっています。

Kylix 1
RTLVersion=14.00
(未定義)
Delphi 6 (Gold)
RTLVersion=14.10
CompilerVersion=14.01
Delphi 6 (Update Pack 1)
RTLVersion=14.11
CompilerVersion=14.01
Delphi 6 (Update Pack 2)
RTLVersion=14.20
CompilerVersion=14.01
C++Builder 6
RTLVersion=14.20
CompilerVersion=14.01
Kylix 2
RTLVersion=14.20
CompilerVersion=14.10
Kylix 3
RTLVersion=14.50
CompilerVersion=14.50
Delphi 7
RTLVersion=15.00
CompilerVersion=15.00
Delphi 8 for .NET
RTLVersion=16.00
CompilerVersion=16.00
Delphi 2005
RTLVersion=17.00
CompilerVersion=17.00
Delphi 2006
RTLVersion=18.00
CompilerVersion=18.00
Delphi 2007
RTLVersion=18.00
CompilerVersion=18.50
Delphi 2007 for .NET
RTLVersion=19.00
CompilerVersion=19.00
Delphi/C++Builder 2009
RTLVersion=20.00
CompilerVersion=20.00
Delphi/C++Builder 2010
RTLVersion=21.00
CompilerVersion=21.00
Delphi/C++Builder XE
RTLVersion=22.00
CompilerVersion=22.00
Delphi/C++Builder XE2
RTLVersion=23.00
CompilerVersion=23.00
FireMonkeyVersion=16.1(Update 2), 16.2(Update 3), 16.3(Update 4)
Delphi/C++Builder XE3
RTLVersion=24.00
CompilerVersion=24.00
FireMonkeyVersion=17.0
Delphi/C++Builder XE4
RTLVersion=25.00
CompilerVersion=25.00
FireMonkeyVersion=18.0
Delphi/C++Builder XE5
RTLVersion=26.00
CompilerVersion=26.00
FireMonkeyVersion=19.0
Delphi/C++Builder XE6
RTLVersion=27.00
CompilerVersion=27.00
FireMonkeyVersion=20.0
Delphi/C++Builder XE7
RTLVersion=28.00
CompilerVersion=28.00
FireMonkeyVersion=21.0
Delphi/C++Builder XE8
RTLVersion=29.00
CompilerVersion=29.00
FireMonkeyVersion=22.0
Delphi/C++Builder 10 Seattle
RTLVersion=30.00 *
CompilerVersion=30.00
FireMonkeyVersion=23.0
Delphi/C++Builder 10.1 Berlin
RTLVersion=31.00 *
CompilerVersion=31.00
FireMonkeyVersion=240 **
Delphi/C++Builder 10.2 Tokyo
RTLVersion=32.00 *
CompilerVersion=32.00
FireMonkeyVersion=250 **
Delphi/C++Builder 10.3 Rio
RTLVersion=33.00 *
CompilerVersion=33.00
FireMonkeyVersion=260 **
Delphi/C++Builder 10.4 Sydney
RTLVersion=34.00 *
CompilerVersion=34.00
FireMonkeyVersion=270 **
Delphi/C++Builder 11 Alexandria
RTLVersion=35.00 *
CompilerVersion=35.00
FireMonkeyVersion=270 ** ***
Delphi/C++Builder 12 Athens
RTLVersion=36.00 *
CompilerVersion=36.00
FireMonkeyVersion=290 **
* C++Builder 10 Seattle以降のClangベースの新しいC++コンパイラ(#if defined(__clang__))ではRTLVersionではなくRTLVersionCを使用する必要がある→Clang 拡張 C++ コンパイラと旧世代の C++ コンパイラの違いを参照。
** Delphi/C++Builder 10.1 Berlin以降ではFireMonkeyVersion(FMX.Typesユニット)の定義がComp型からInteger型となり、値も240(0xF0)のように10倍になっているため、注意が必要です。
*** Delphi/C++Builder 11 AlexandriaでFireMonkeyVersionが10.4 Sydneyと同じ270と定義されています(不具合と思われます)。

注意しなければならないのは、RTLVersion(C)、CompilerVersion、FireMonkeyVersion(10 Seattleおよびそれ以前)のいずれも実数型の値なので、小数点以下を含むもの(Delphi/C++Builder 6の14.xあたり)は丸めによる誤差を考慮して評価する必要がある、という点です。

実際の使い道としては
  • Kylixのバージョン判定(いまさら)
  • ジェネリクス、無名関数といった新機能のサポート状況の判定
くらいでしょうか(UpdateやHotfixの適用状況がわかるように、もう少し真面目に値を変えてほしいところです)。

StringがAnsiStringかUnicodeStringかは標準条件シンボルUNICODEを使用して
{$IFDEF UNICODE}
// StringはUnicodeString
{$ELSE}
// StringはAnsiString
{$ENDIF}

で判定できますが、ジェネリクス/無名関数が使用できるかどうかは
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 20.0}
// ジェネリクス/無名関数使用可能(Delphi 2009以降)
{$ELSE}
// ジェネリクス/無名関数使用不可(Delphi 6-2007)
{$ENDIF}
{$ELSE}
// ジェネリクス/無名関数使用不可(Delphi 5以前)
{$ENDIF}

このように判定することができます。

またFireMonkeyVersionはVER230でもRTM/Update 1では定義されていないため、
{$IF Declared(FireMonkeyVersion) and (FireMonkeyVersion > 16.0)}
...
{$IFEND}

のように定義済かどうかの確認も必要です。

元ねたはDelphi Tips - 0086あたりとDelphi XE - Q&A (Internet Archive)。標準条件シンボルと同様に、有効な情報が(ヘルプを含め)あまりないのは改善をお願いしたいところです。

2011/09/02追記: Delphi/C++Builder XE2関係を追加。

2012/09/02追記: Delphi/C++Builder XE3関係およびFireMonkeyVersionに関する記述を追加。

2013/09/12追記: Delphi/C++Builder XE4/XE5関係を追加。

2014/04/15追記: Delphi/C++Builder XE6関係を追加。

2014/09/02追記: Delphi/C++Builder XE7関係を追加。

2015/04/07追記: Delphi/C++Builder XE8関係を追加。

2015/09/01追記: Delphi/C++Builder 10 Seattle関係を追加。

2016/04/20追記: Delphi/C++Builder 10.1 Berlin関係を追加。

2017/03/23追記: Delphi/C++Builder 10.2 Tokyo関係を追加。

2018/11/26追記: Delphi/C++Builder 10.3 Rio関係を追加。

2020/06/01追記: Delphi/C++Builder 10.4 Sydney関係を追加。

2021/09/10追記: Delphi/C++Builder 11 Alexandria関係を追加。

2023/11/09追記: Delphi/C++Builder 12 Athens関係を追加。

1 件のコメント:

おかぽん さんのコメント...

古~い環境のメンテしていて気がつきましたが、Delphi 5 では、CONDITIONALEXPRESSIONS内の
{$ELSE}が認識されてしまうので、以下のようにしないと、Delphi 5 (以前?)ではコンパイルができない罠がありました。

{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 20.0}
// ジェネリクス/無名関数使用可能(Delphi 2009以降)
{$IFEND}
{$IF CompilerVersion < 20.0}
// ジェネリクス/無名関数使用不可(Delphi 6-2007)
{$IFEND}
{$ELSE}
// ジェネリクス/無名関数使用不可(Delphi 5以前)
{$ENDIF}

今更 Delphi 5 以前の話されても・・・なんですけども。