ここで緊張していることがいくつかあるので、それらを列挙させてください。
- 集中化/モジュール性:集中化について考えるのが普通です。これにより、予想されるエラーの種類を簡単にチェックし、おおよそのお土産などからエラーを回復できます。ただし、モジュール性では、各モジュールが新しいエラー
- 動的初期化中にエラーが発生する可能性があります(コードの実行を禁止しない限り、チェックは簡単ではありません)。存続期間の問題を回避するには、静的初期化中に初期化されるオブジェクトのみに依存することをお勧めします(これは文字列リテラルの場合です)。 、 例えば)
一般に、私が見た中で最も単純なことは、ある積分定数を使用してエラーを識別し、次に他の情報(潜在的には多くの情報)を取得できる側にテーブルを置くことでした。たとえば、Clangはこのシステムを診断に使用します。プリプロセッサを有利に使用することで、繰り返しを避けることができます。
次のようなヘッダーを使用します。
#define MYMODULE_ERROR_LIST \
ERROR(Code, "description") \
...
#define ERROR(Code, Desc) Code,
class enum ErrorCode: unsigned {
MYMODULE_ERROR_List
NumberOfElements
};
#undef ERROR
struct Error {
ErrorCode code;
char const* description;
};
Error const& error(ErrorCode ec);
そして、配列を見つけるための簡単なソースファイル:
#define ERROR(Code, Desc) { Code, Desc },
Error const ErrorsArray[] = {
MYMODULE_ERROR_LIST
{ErrorCode::NumberOfElements, 0}
};
Error const& error(ErrorCode const ec) {
assert(unsigned(ec) < unsigned(ErrorCode::NumberOfElements) &&
"The error code must have been corrupted.");
return ErrorsArray[ec];
} // error
注:ヘッダーでマクロを定義することの代償は、説明の文言のわずかな変更が、列挙型に応じてすべてのコードの再コンパイルを意味することです。個人的には、私のものはテストされたものよりもはるかに速く構築されるので、私はあまり気にしません。
これは非常に効率的なスキームです。DRY(Do n't Repeat Yourself)を尊重するため、コード記述マッピングが正確であることも保証されます。マクロを調整して、説明だけでなく、より多くのERROR
情報(カテゴリなど)を含めることができます。Error
タイプがである限りis_trivially_constructible
、配列は静的に初期化できるため、ライフタイムの問題を回避できます。
残念ながら、enum
モジュール性はあまり得意ではありません。また、各モジュールに独自の機能を持たせるenum
ことは、エラーを均一に処理することになるとすぐに退屈になる可能性があります(Error
構造体はを使用できますunsigned code;
)。
中央リポジトリを超えたい場合は、より複雑なメカニズムが必要ですが、それがあなたに適しているように思われたので、この制限については言及しません。