多くの場合、ゲームなどのリアルタイムアプリケーションでロギングを目的として、各エンティティに名前を付けます。これにより、ユニークな名前を介してエンティティを見つけることは、一意の数字や他の形式の識別子を見るよりも簡単になるため、エラーの追跡が簡単になります。しかし、文字列は巨大で、それらをコピーして比較するのは遅いため、パフォーマンスクリティカルコードでは使用できないことがよくあります。
1つの解決策は、整数のみであり、コピーして比較するために小さく、速い弦です。しかし、ハッシュは、ロギングとデバッグの目的で必要な元の文字列値を取得することはできません。さらに、衝突の可能性があるため、等しいハッシュコードは必ずしも等しい文字列を意味するわけではありません。このチャンスは小さいですが、バグを見つけるのが難しいソースです。
別の解決策は、弦インターンです。 String Interningは、各文字列が1回だけ保存され、インデックスなどを介して参照されるグローバルルックアップテーブルを使用します。コピーと比較も高速ですが、まだ完璧ではありません。実行時にのみアクセスできます。スイッチの場合、コンパイル時に値を取得することは不可能です。
したがって、一方では、高速で軽量の識別子が必要ですが、他方では名前を取り戻す方法も必要です。
このオープンソースライブラリは、2つのソリューション間のクラスString_IDの形式でのミックスを提供します。各オブジェクトは、ハッシュされた文字列値と、元の文字列値が保存されているデータベースへのポインターを保存します。これにより、必要に応じて文字列値を取得しながら、ハッシュされた文字列からパフォーマンスのメリットを取得できます。さらに、データベースは、カスタム衝突ハンドラーを介して処理できる衝突を検出できます。コンパイル時間ハッシュされた文字列値を作成して、一定の式として使用するユーザー定義のリテラルがあります。
データベースは、特定のインターフェイスクラスから派生した任意のユーザー定義型のタイプにすることができます。いくつかの事前に定義されたデータベースがあります。これには、何も保存しないダミーデータベース、他のデータベースがスレッドセーフにするためのアダプター、文字列を効率的に保存および取得するための高度に最適化されたデータベースが含まれます。 typedef default_databaseはこれらのデータベースの1つであり、次のcmakeオプションで設定できます。
foonathan_string_id_database-オフの場合、データベースが完全に無効になっている場合、たとえばダミーデータベースが使用されます。これにより、文字列や衝突チェックを取得することはできませんが、それほど多くのメモリは必要ありません。デフォルトで使用されています。
foonathan_string_id_multithreaded -onの場合、データベースアクセスがミューテックスを介して同期されます。たとえば、スレッドセーフアダプターが使用されます。データベースが無効になっている場合、それは効果がありません。デフォルト値がオンになっています。
特別な発電機クラスがあります。それらは、標準ライブラリの乱数ジェネレーターと同様のインターフェイスを持っていますが、文字列識別子を生成します。これは、自動化された方法で多数の識別子を生成するために使用されます。ジェネレーターは、常に新しい識別子が生成されていることを注意します。これは、衝突ハンドリングと同様のハンドラーを介して制御できます。
例については、例/main.cppを参照してください。
現在、FNV-1A 64ビットハッシュを使用しています。衝突は本当にまれです。私は219,606個の英語の単語(小文字)と大量の数字を混ぜたものでテストし、1回の衝突に遭遇しませんでした。これは識別子の通常のユースケースであるため、ハッシュ関数はかなり良好です。さらに、ハッシュ値の適切な分布があり、計算が簡単です。
データベースは、特殊なハッシュテーブルを使用します。バケットインデックスの衝突は、単一のリンクリストを使用した個別のチェーンを介して解決されます。各ノードには、追加のメモリ割り当てなしで文字列が直接含まれます。リンクリストのノードは、ハッシュ値を使用してソートされます。これにより、同じハッシュ値が格納されている文字列が既にあるかどうかを効率的に取得して確認できます。これにより、以前に使用されたSTD :: UNORDERED_MAPよりも非常に効率的かつ高速になります(少なくともベンチマークに使用したLIBSTDC ++実装よりも高速)。
このライブラリは、次のコンパイラの下にまとめられています。
Constexpr、NoExcept、Override、およびLiteral Operatorの互換性オプションと交換用マルコスがあります。アトミックハンドラー機能はオプションで無効にすることができ、デフォルトではGCC 4.6ではサポートしていないためオフにできます。