Ich codiere eine kleine Bibliothek und habe Probleme beim Entwerfen der Ausnahmebehandlung. Ich muss sagen, dass ich (immer noch) durch diese Funktion der C ++ - Sprache verwirrt bin und versucht habe, so viel wie möglich zu diesem Thema zu lesen, um zu verstehen, was ich tun müsste, um mit Ausnahmeklassen richtig zu arbeiten.
Ich entschied mich für einen system_error
Ansatz, der sich von der STL-Implementierung der future_error
Klasse inspirieren ließ .
Ich habe eine Aufzählung mit den Fehlercodes:
enum class my_errc : int
{
error_x = 100,
error_z = 101,
error_y = 102
};
und eine einzelne Ausnahmeklasse (gesichert durch eine error_category
Art von Strukturen und alles andere, was das system_error
Modell benötigt ):
// error category implementation
class my_error_category_impl : public std::error_category
{
const char* name () const noexcept override
{
return "my_lib";
}
std::string message (int ec) const override
{
std::string msg;
switch (my_errc(ec))
{
case my_errc::error_x:
msg = "Failed 1.";
break;
case my_errc::error_z:
msg = "Failed 2.";
break;
case my_errc::error_y:
msg = "Failed 3.";
break;
default:
msg = "unknown.";
}
return msg;
}
std::error_condition default_error_condition (int ec) const noexcept override
{
return std::error_condition(ec, *this);
}
};
// unique instance of the error category
struct my_category
{
static const std::error_category& instance () noexcept
{
static my_error_category_impl category;
return category;
}
};
// overload for error code creation
inline std::error_code make_error_code (my_errc ec) noexcept
{
return std::error_code(static_cast<int>(ec), my_category::instance());
}
// overload for error condition creation
inline std::error_condition make_error_condition (my_errc ec) noexcept
{
return std::error_condition(static_cast<int>(ec), my_category::instance());
}
/**
* Exception type thrown by the lib.
*/
class my_error : public virtual std::runtime_error
{
public:
explicit my_error (my_errc ec) noexcept :
std::runtime_error("my_namespace ")
, internal_code(make_error_code(ec))
{ }
const char* what () const noexcept override
{
return internal_code.message().c_str();
}
std::error_code code () const noexcept
{
return internal_code;
}
private:
std::error_code internal_code;
};
// specialization for error code enumerations
// must be done in the std namespace
namespace std
{
template <>
struct is_error_code_enum<my_errc> : public true_type { };
}
Ich habe nur eine kleine Anzahl von Situationen, in denen ich Ausnahmen auslöse, die durch die Aufzählung der Fehlercodes veranschaulicht werden.
Das oben Gesagte passte nicht gut zu einem meiner Rezensenten. Er war der Meinung, dass ich eine Hierarchie von Ausnahmeklassen mit einer abgeleiteten Basisklasse std::runtime_error
hätte erstellen sollen, da der in die Bedingung eingebettete Fehlercode Dinge vermischt - Ausnahmen und Fehlercodes - und es mühsamer wäre, sich mit dem Punkt zu befassen der Handhabung; Die Ausnahmehierarchie würde auch eine einfache Anpassung der Fehlermeldung ermöglichen.
Eines meiner Argumente war, dass ich es einfach halten wollte, dass meine Bibliothek nicht mehrere Arten von Ausnahmen auslösen musste und dass die Anpassung auch in diesem Fall einfach ist, da sie automatisch durchgeführt wird - dem error_code
ist eine error_category
zugeordnet, die das übersetzt Code zur richtigen Fehlermeldung.
Ich muss sagen, dass ich meine Wahl nicht gut verteidigt habe, ein Beweis dafür, dass ich immer noch einige Missverständnisse in Bezug auf C ++ - Ausnahmen habe.
Ich würde gerne wissen, ob mein Design Sinn macht. Was wären die Vorteile der anderen Methode gegenüber der von mir gewählten, da ich zugeben muss, dass ich das auch nicht sehe? Was könnte ich tun, um mich zu verbessern?