実験:空のstd::vectorから要素を取得するとどうなるか?

ふとした疑問

std::vectorには最後尾の要素を取得するbackというメソッドがあります。 もし、vectorが空の場合backメソッドを呼ぶとどうなるのか実験してみました。

書いたコードはこんな感じ。期待する動作は空要素を返すか、何らかの例外を投げてくれるか。

#include <vector>
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
    std::vector<std::string> StrList;

    try {
            auto v = StrList.back();
        std::cout  << "Length = " << v.length() << std::endl;
    } catch (std::exception& e) {
       std::cout  << "exception:" << e.what()  << std::endl;
    }

    return 0;
}

実験結果

試したのはbcc32c 7.40、MS-C 19.16.27026.1 、gcc 7.3.0、clang 6.0.0。gccとclangはWSLで確認。 結果は以下の通り。

コンパイラ 結果
bcc32c 例外やエラーなし。
MS-C 例外やエラーなし。
gcc segmentation fault
clang segmentation fault

Windows処理系だと、例外すら発生せずにどこかでコケている感じ。 bcc32cはデバッガで確認したり、Dinkumware STLのソースを確認すると、単に「end() - 1」だったので、そりゃあコケるわなと。

まとめのようなモノ

ということで、コンテナから要素を取り出す場合emptyとかでチェックしないと駄目というオチでした。

FireDAC / C++Builder のちょっとした小ネタ×3

その1:結果が1行、1列しかないデータを取得する場合

データベース開発をしていてよくあるのがクエリを発行して1個のスカラー値しか取らないケース。
例えば、連番とか、翌営業日とか、件数などなど。
こんな場合、TFDQuery::OpenメソッドでSQLを発行して、データセットから値を取得して、クローズするのはあまり「美しくない」です。
そんな場合に打って付けなのが、TFDConnection::ExecSQLScalarメソッドです。
このメソッドはTFDQuery::Openメソッドと同じようにクエリを発行するのですが、単一のスカラー値をVariantで返却します。データセットの操作とかは不要です。
文字通り、単一のスカラー値を取得する場合に使ってみて下さい。

その2:データ型マッピングと日付型

FireDACのデータ型マッピングを皆様お使いでしょうか?
この機能はRDBMSとクライアント間のデータ変換ルールを定義します。ドキュメントでは数値の変換ルールが記載されていますが、日時型はどうでしょうか?
FireDACというか、Delphi / C++Builderのデータセットで使われる日時型は以下の2つです。

さて、この両者の違いは秒未満の精度の違いです。RDBMSの日時型がどちらにマッピングされるのは、RDBMSに依存します。
FireDACのウリはマルチデータベース対応ですが、ここで依存性が発生するのはちょっとよろしくないです。
そこで、FireDAC接続エディタを使い明示的にマッピングすることで、日時型をどちらかに寄せることが出来ます。これで、TFDDConnectionで違うRDBMSに接続しても型変換を担保することが出来ます。

f:id:A7M:20181218225520p:plain
FireDAC接続エディタ

ちなみに、SQL ServerのDateTime2型は何もしないと文字列型にマッピングされます。
これは、データベースドライバの関係なので、SQL Native Client をインストールすることを強くお勧めします。(Microsoft SQL Server への接続(FireDAC) - RAD Studio

その3:FireMonkeyとC++文字列リテラル

C++Builderで作ったライブラリをFireMonkeyのプロジェクトにポーティングをすることは良くあるかと思います。
プラットフォーム毎に文字列リテラル文字コードを意識しないと文字化けします。
# ええ、テストプログラムで見事にやらかしました。
最近だと、Unicodeを意識して、文字列の接頭辞にuとかu8とかLとか付けますが、_D()マクロを使うとプラットフォームに合わせた接頭辞を選択してくれるので大変便利です。
詳細は、以下のDocWikiの記事を参考にしてください。
C++ におけるマルチデバイス アプリケーションについての考慮事項 - RAD Studio

Delphiでラムダ式

Delphi 10.3 Rioでは、Delphi言語のエンハンスとして、インライン変数宣言インライン変数の型推論が導入されました。

これによりDelphiラムダ式(無名メソッド)が書きやすくなりましたのでご紹介します。

ソースコードラムダ式を使うメリットとしては以下が挙げられます。

  • スレッドやコールバックのようなロジックをインラインで書くことによって可読性が向上する。
  • 判定条件などの処理をオブジェクトとして持つことで記載が簡潔になる。

10.2まで、Delphiで無名メソッドを使用するにはTypeブロック内で以下のように宣言する必要があります。

program LTDel;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  System.SysUtils;
type
  TMyFunc = reference to procedure();
var
  f0 : TMyFunc;
  f1 : TMyFunc;
begin
  f0 :=
    procedure begin
      WriteLn('Hello,')
    end;
  f1 :=
    procedure begin
      WriteLn('World!')
    end;
  f0();
  f1();
end.

そして、10.3 Rioからは、以下のように記述出来ます。ラムダ式を配列として宣言した例です。型推論のおかげでかなりラムダ式しています。

program LTDel;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  System.SysUtils;

begin
  var f := [
    procedure begin
      WriteLn('Hello,')
    end,
    procedure begin
      WriteLn('World!')
    end
  ];

  f[0]();
  f[1]();
end.

一見、ラムダ式は難しく見えますが、理解して使い始めた途端に可読性が良くなりますので、是非とも使ってみて下さい。

続・RAD Studio 10.2.2 Tokyo Starterをちょっとだけいじってみた。

今度はJCLとJVCLのインストールに挑戦。

JCLとJVCLはGetItからダウンロード・インストールできるのだけど、JVCLはパッケージがインストールされない。

コンパイル済みのバイナリがあるのだけど、こっちもこっちで同じ。

・30761 Jedi Code Library Snapshot Binary Installer for 10.2
http://cc.embarcadero.com/Item/30761

・30762 Jedi Visual Component Library Snapshot Bin-Installer 10.2
http://cc.embarcadero.com/Item/30762

仕方ないので、JVCLは上記インストーラーの展開先から手動でインストール。
以下の手順で(多分)問題なし。

  1. C:\DelphiComponents\JVCL\packages\D25 Packages.groupprojをオープン
  2. プロジェクトグループから以下のパッケージを削除
    • JvDotNetCtrls
    • JvDotNetCtrlsDesign
    • JvDB
    • JvDBDesign
  3. 「プロジェクトマネージャ」から「全てをビルド」
  4. バイナリは、C:\Users\Public\Documents\Embarcadero\Studio\19.0\Bplにできるので、これらを[コンポーネント| パッケージのインストール]でインストール。

ただし、このままだとC++Buiderから使えないので、各プロジェクトオプションの[Delphiコンパイラ|出力 - C/C++]のC/C++ 出力ファイルの生成を「すべての C++Builder ファイル (パッケージ ライブラリを含む) を生成」に設定。

f:id:A7M:20180103213121p:plain

今日はここで力尽きた。やっぱり、Pro以上じゃないと駄目かな…。

RAD Studio 10.2.2 Tokyo Starterをちょっとだけいじってみた。

はてなダイアリーからはてなブログに移行しての第一弾。
ここ数年放置状態だったけど、これからは更新頻度が上がるはず。

ということで、RAD Studio 10.2.2 Tokyoのレビューのような物。

しかし、まぁ、立ち上げていきなりdark themeで立ち上がって驚いた。

f:id:A7M:20180101141449p:plain

Visual Studio CodeとかAtomのようなモダンなエディタの配色がこんな感じだから、その辺のトレンドに合わせてきたのかな。

C++コンパイラLLVM 3.3.1がベース。

f:id:A7M:20180101151458p:plain

 Boostは最初からインストールされているのでは無く、NuGetのようにGetItからダウンロード。バージョンは2013年11月リリースの1.55。流石に旧コンパイラは無理だけど、せめてCLANGベースのは追随して欲しい。物は試しと1.66のビルドに挑戦したけどコンパイラがお亡くなりになったので断念。

折角だからアプリをビルドしてみたら以下のメッセージが表示。

MSBuildToolsPath is not specified for the ToolsVersion "14.0" defined at "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0", or the value specified evaluates to the empty string.
[致命的エラー] MSBuildToolsPath is not specified for the ToolsVersion "14.0" defined at "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0", or the value specified evaluates to the empty string.

どうも、64bitOSでレジストリの MSBuildの値に不整合があるみたい。

support.embarcadero.com

素直に当該部分(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0)を削除すればサクッと動作。

f:id:A7M:20180101153254p:plain

 JVCLのようなサードパーティーコンポーネントはどうなったのかは次のネタで。

 

 

第5回 Delphi talksに参加してきた

この手のイベントに参加するのは本当に久しぶり。楽しい時間を過ごせました。
LTのネタは諸事情により2年3ヶ月ほど塩漬け状態な、コードフォーマッタープラグインネタ。

あまり役に立たない、昨日使用したプレゼンを公開します。
ちなみに、プラグインそのもの(RAD Studio XE用)はhttp://a7m.sakura.ne.jp/APPS/UncrustifyRS_1.00.7zにて公開中。ソースはMPLで配布しているので、ご自由にお使いください。ビルドし直せばXE4とかでも動くはず。(多分)
デブキャンでネタにしたOpen Tools APIについてはここで公開しています。