エラー コード (int) と文字列の説明 (任意の文字列) を 1 か所だけで宣言する方法が必要でしたが、上記の例のいずれもそれを許可していません。
そこで、int と string の両方を格納し、int->string 変換の静的マップを維持する単純なクラスを宣言しました。「auto-cast to」int 関数も追加しました。
class Error
{
public:
Error( int _value, const std::string& _str )
{
value = _value;
message = _str;
#ifdef _DEBUG
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found != GetErrorMap().end() )
assert( found->second == message );
#endif
GetErrorMap()[value] = message;
}
// auto-cast Error to integer error code
operator int() { return value; }
private:
int value;
std::string message;
typedef std::map<int,std::string> ErrorMap;
static ErrorMap& GetErrorMap()
{
static ErrorMap errMap;
return errMap;
}
public:
static std::string GetErrorString( int value )
{
ErrorMap::iterator found = GetErrorMap().find( value );
if ( found == GetErrorMap().end() )
{
assert( false );
return "";
}
else
{
return found->second;
}
}
};
次に、以下のようにエラー コードを宣言するだけです。
static Error ERROR_SUCCESS( 0, "The operation succeeded" );
static Error ERROR_SYSTEM_NOT_INITIALIZED( 1, "System is not initialised yet" );
static Error ERROR_INTERNAL( 2, "Internal error" );
static Error ERROR_NOT_IMPLEMENTED( 3, "Function not implemented yet" );
次に、int を返す任意の関数で 1 を返すことができます。
return ERROR_SYSTEM_NOT_INITIALIZED;
また、ライブラリのクライアント プログラムを呼び出すと、「システムはまだ初期化されていません」というメッセージが表示されます。
Error::GetErrorString( 1 );
また:
Error::GetErrorString( ERROR_SYSTEM_NOT_INITIALIZED );
私が見る唯一の制限は、静的なエラー オブジェクトを宣言する .h ファイルが多くの .cpp に含まれている場合に何度も作成されることです (そのため、コンストラクターで _DEBUG テストを実行して、マップの一貫性を確認します)。何千ものエラー コードがない場合、問題にはならないはずです (回避策があるかもしれません...)。