mixinによりコンパイル時にコードを生成するDの能力の好例がビット操作です。
Dはビット操作のために以下の演算子を提供します:
& ビット単位論理積
| ビット単位論理和
~ ビット反転
<< ビット符号あり左シフト
>> ビット符号あり右シフト (上位ビットの符号が保持されます)
>>> ビット符号なし右シフト
ビット操作の一般的な例はビットの値を読むことです。Dは最も一般的なタスクのために
core.bitop.btを提供しますが、ビット操作に慣れ親しむためには、
ビットのテストの冗長な実装をしてみましょう。:
enum posA = 1;
enum maskA = (1 << posA);
bool getFieldA()
{
return _data & maskA;
}
一般化は1より長いブロックのテストをすることです。そのためブロックの長さの特殊な リードマスクが必要で、データブロックはマスクが適用される前にシフトされます:
enum posA = 1;
enum lenA = 3;
enum maskA = (1 << lenA) - 1; // ...0111
uint getFieldA()
{
return (_data >> posA) & maskA;
}
そのようなブロックの設定は等しくマスクの否定によって定義し、特定のブロック内のみに書込みできます:
void setFieldA(bool b);
{
return (_data & ~maskAWrite) | ((b << aPos) & maskAWrite);
}
std.bitmanipカスタムビット操作コードを書くことは非常に面白く、Dはそのための完全なツールボックスを提供します。
しかし非常にエラーを引き起こしやすく保守がしづらいため大抵の場合そのようなビット操作はコピー&ペーストはしたくありません。
したがってDではstd.bitmanipが保守性のあり、読みやすいビット操作を書くことをstd.bitmanipとmixinの力で
助けます - パフォーマンスは犠牲になりません。
エクササイズのセクションをご覧ください。BitVectorは定義されていますが、まだXビットを使い、
普通の構造体とほとんど見分けがつきません。
std.bitmanipとcore.bitop少ないメモリ消費を必要とする
アプリケーションのための非常に有用な更に多くのヘルパがあります。
コンパイラは、bool, byte, char のようなOSのメモリレイアウト (size_t.sizeof)
よりも小さいサイズの変数に対してパディングを挿入するため、アライメントの大きいフィールドから書くと良いでしょう。