Delphiからの移植に際して
Delphiのソースコードがあって、それをなんとかC++ Builder CEで使いたい場合は、”翻訳”すればいいんですが、時にどうしたらいいか困る場面が出てきます。CE版では混在できませんからね。
その1
Delphiの集合型を扱う場合。例として、DEKOさんの記事、
の中のcode fragmentとして、
for var i:=1 to ParamCount do
begin
var s := ParamStr(i);
if not CharInSet(s[1], ['-', '/']) then
begin
FileIdx := i;
Break;
end;
end;
の緑部分が該当します。緑部分が集合体ですが、まんまコンパイルしようとすると、C++では[]はラムダ式なので、当然エラーになります。で、上記コードはコマンドラインの解析をしようとしていて、argv[i]の中に’-‘ないし’/’が文字としてあったら、それはコマンドラインオプションとして扱うべきものという原作者の意図がわかっていれば、集合体に拘泥することなく翻訳すれば良いです。無理に原文を活かして翻訳できなくもないですが、普通はしませんよね。意訳します。が、敢えて”直訳”するのであれば、TSysCharsetを宣言してインスタンスを作って、上記部分に当てはめればよいので、1行では書けませんが、
TSysCharSet mySet;
mySet << '/' << '-' ;
char s = ParamStr[i]の先頭文字
if (CharInSet(s, mySet)) {
ShowMessage("contains");
}
でよいですね。実はUnicodeStringなParamStr[i]の先頭文字一字を取り出すのって、意外に面倒ですよ。
その2 Delphiの集合体の続き
VCLでもFMXでもネットワークプログラムを書く時に、Indyにお世話になることも多いですよね。例として、TIdHTTPを挙げましょうか?このコンポーネントを使う時に、場合によってはプロパティーの設定が必要になることがあります。図として示しましょう。

TIdHTTPのインスタンスであるIdHTTP1のプロパティであるHTTPOptionsですが、上図のようにデフォルトでは、hoForceEncodeParamsのみがTrueになっています。これが実はDelphiの集合体なんです。設定を変えるには、このオブジェクトインスペクタで、TrueないしFalseをチェックすればいいだけです。少しいじると、

集合体の表記のほうも。変わって、
[hoInProcessAuth,hoForceEncodeParams]
になりました。ここまでは無問題です。ところがTIdHTTPそのものを動的に割り付けた場合、つまり
TIdHTTP* http = new TIdHTTP();
とするとインスタンスであるhttpの普通のプロパティは設定できます。が、
TIdHTTP* http = new TIdHTTP();
http->AllowCookies = false;
http->HTTPOptions = [hoInProcessAuth,hoForceEncodeParams];
が、これは冒頭と同じでラムダ式なの?ということでエラーになります。コンパイラ様に勘弁してもらうためには、冗長ですけど
http->HTTPOptions = http->HTTPOptions << hoInProcessAuth << hoForceEncodeParams;
http->HTTPOptions = http->HTTPOptions >> hoKeepOrigProtocol;
のように書かないといけません。ながったらしいですね( bit awkward)。少しだけより簡潔に書きたければ、
http->HTTPOptions >>= hoNoReadChunked;
という書き方もできますが、複数の設定はできませんから1行ずつになります。いずれにしてもTrueにしたければ、 << で注入して、Falseにしたければ >> で抜き出すようなイメージですかね。
動的割り付けがいいのは、ソースコードに一切合切全部書けることで、HTTPOptionsの設定をこうしてね、という図が要らない点ですね。
その3 with ~ do somethingの構文
例を示すと、というかGemini君によれば、
Delphiの with...do 文は、レコードやオブジェクトのフィールド・プロパティ・メソッドを、オブジェクト名を省略して直接参照するための構文です。コードの記述量を減らせる一方で、バグの原因や可読性の低下を招くこともあるため、注意が必要な機能でもあります。基本的な使い方対象となるオブジェクトやレコードを with の後に指定し、do の後のブロックで各メンバを直接呼び出します。pascalwith Edit1 do
begin
Text := 'Hello, Delphi';
Width := 200;
Color := clWhite;
end;
コードは注意してご使用ください。上記は、以下のように書くのと等価です。
pascal
Edit1.Text := 'Hello, Delphi';
Edit1.Width := 200;
Edit1.Color := clWhite;
ということですが、初めて見たときはどうするんじゃ、となりますが、下のように解釈してC++に翻訳すればよろしい。地道に翻訳します。Geminiが言うように、簡潔に書けますが、問題もあるので、最近はなるべくこの書き方を止める方向と聞いてます。比較的古いDelphiのソースで見かけることが多いです。


コメント