プラグマ
プリプロセッサディレクティブは、コンパイラと相互作用するための方法である。コンパイラに特別な情報を提供したり、コンパイラから情報を取得したりするために使用される。テンプレート以外のコードでも有用だが、pragma(msg)
はテンプレートのデバッグ時に役立つ。
各コンパイラベンダーは、以下の必須のpragma
ディレクティブに加えて、独自の ディレクティブを自由に導入することができる。
pragma(msg)
コンパイル時にstderr
にメッセージを表示する。コンパイルされたプログラムの実行時にはメッセージは表示されない。
例えば、テンプレートパラメータの型を、おそらくデバッグ中に公開するために、次のpragma(msg)
が使用されている。
型'int'および'double'で呼び出された場合
型'string'および'char'で呼び出された場合
pragma(lib)
コンパイラに、プログラムを特定のライブラリにリンクするよう指示する。これは、システムにすでにインストールされているライブラリにプログラムをリンクする最も簡単な方法だ。
例えば、次のプログラムは、コマンドラインでライブラリを指定しなくても、curl
ライブラリにリンクされる。
pragma(inline)
関数をインライン化すべきかどうかを指定する。
すべての関数呼び出しには、ある程度のパフォーマンスコストがかかる。関数呼び出しには、関数への引数の渡し、呼び出し元への戻り値の返送、および関数の呼び出し元を記憶するためのいくつかの管理情報の処理が含まれる。これにより、関数の呼び出し元が関数の呼び出し元を記憶し、関数の呼び出し元が関数の呼び出し元を記憶することで、関数の呼び出し元が関数の呼び出し元を記憶することで、関数の呼び出し元が関数の呼び出し
このコストは、通常、呼び出し元および呼び出し先が実行する実際の作業コストに比べれば、ごくわずかである。しかし、場合によっては、特定の関数を呼び出すという行為自体が、プログラムのパフォーマンスに測定可能な影響を与えることがある。これは、関数本体が比較的高速で、何度も繰り返される短いループから呼び出される場合に特に発生しやすい。
次のプログラムは、ループから小さな関数を呼び出し、戻り値が条件を満たす場合にカウンタを加算する。
このコードは、std.datetime.stopwatch.StopWatch
を使用して、ループ全体の実行時間を測定している:
674ミリ秒
-inline
コンパイラスイッチは、関数インライン化と呼ばれるコンパイラ最適化を実行するようにコンパイラに指示する。
関数がインライン化されると、その本体は呼び出された場所にコードに挿入され、実際の関数呼び出しは発生しない。以下は、インライン化後にコンパイラがコンパイルする同等のコードだ。
このプログラムをテストしたプラットフォームでは、関数呼び出しを削除することで実行時間が約 40% 短縮された。
407ミリ秒
関数のインライン化は大きなメリットがあるように見えるが、すべての関数呼び出しに適用できるわけではない。そうすると、インライン化された関数の本体がコードが大きくなりすぎて、CPUの命令キャッシュに収まらなくなるからだ。その結果、コードの速度が低下してしまう可能性がある。そのため、どの関数呼び出しをインライン化するかは、通常、コンパイラに任されている。
ただし、コンパイラがこの決定を支援する方が有益な場合もある。inline
プリプロセッサディレクティブは、コンパイラのインライン化決定に指示を出し:
pragma(inline, false)
:-inline
コンパイラスイッチが指定されている場合でも、特定の関数をインライン化しないようにコンパイラに指示する。pragma(inline, true)
: コンパイラスイッチ-inline
が指定されている場合、特定の関数を必ずインライン化するようにコンパイラに指示する。これにより、コンパイラがそのような関数をインライン化できない場合、コンパイルエラーが発生する。(このプラグマの正確な動作は、お使いのコンパイラによって異なる場合がある。)pragma(inline)
: インライン化動作をコンパイラコマンドラインの設定に戻す:-inline
が指定されているかどうかに関わらず。
これらのプラグマは、それらが記述されている関数に影響を与えるだけでなく、スコープやコロンと組み合わせて複数の関数に影響を与えることもできる。
プログラムの実行速度を向上させる別のコンパイラスイッチとして、 がある。これはコンパイラに最適化アルゴリズムをさらに実行するように指示する。ただし、これらのアルゴリズムは多くの時間を要するため、プログラムの実行速度向上はコンパイル速度の低下を伴う。-O
pragma(startaddress)
プログラムの開始アドレスを指定する。開始アドレスは通常、Dランタイム環境によって割り当てられるため、このプリミティブを使用する可能性はほとんどない。
pragma(mangle)
シンボルを、デフォルトのネームマングリング方法とは異なる方法でネームマングリングすることを指定する。ネームマングリングとは、リンカが関数とその呼び出し元を識別する方法のことだ。このプラグマは、DコードがDのキーワードであるライブラリ関数を呼び出す必要がある場合に役立つ。
例えば、Cライブラリにoverride
という関数がある場合、override
はDのキーワードであるため、Dからこの関数を呼び出すには別の名前を使用する必要がある。ただし、リンカが関数を識別できるように、その別の名前もライブラリ内の実際の関数名としてマングリングする必要がある。