我正在编写一个小型库,在设计异常处理时遇到了一些麻烦。我必须说,我(仍然)对C ++语言的此功能感到困惑,并且我尝试尽可能多地阅读该主题,以了解如何正确使用异常类将要做什么。
我决定使用一种system_error
方法,该方法从future_error
该类的STL实现中获得启发。
我有一个包含错误代码的枚举:
enum class my_errc : int
{
error_x = 100,
error_z = 101,
error_y = 102
};
和一个异常类(由error_category
结构类型和system_error
模型所需的所有其他内容支持):
// 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 { };
}
在少数情况下,我抛出由错误代码枚举说明的异常。
上面的内容与我的一位审阅者不太合。他认为,我应该使用派生自std::runtime_error
其的基类来创建异常类的层次结构,因为将错误代码嵌入条件中会混合各种东西(异常和错误代码),并且处理一个问题将更加繁琐处理;异常层次结构还可以轻松自定义错误消息。
我的论据之一是,我想保持简单,我的库不需要抛出多种类型的异常,并且在这种情况下,自定义也很容易,因为它是自动处理的- error_code
具有error_category
与之关联的翻译编码为正确的错误消息。
我不得不说我没有很好地捍卫自己的选择,这证明了我对C ++异常还有一些误解。
我想知道我的设计是否合理。我不得不承认我也看不到另一种方法比我选择的方法有什么优势?我该怎么做才能改善?