我使用std :: error_code,並有一堆錯誤的定義(使用枚舉類)和註冊。std :: error_code,my_error :: check_block == my_error :: validate && my_error :: accept_block == my_error :: validate
我有一個非常普遍的錯誤,現在稱爲my_error :: validate,但要在我的庫中提供更具體的版本。一般人會想用:
if (ec == bc::error::validate)
// ...
但是有時候他們可能希望看到與該的std :: ERROR_CODE相關的特定錯誤或打印錯誤消息。
// ec.message() says "check_block() failed to do XYZ"
assert(ec == bc::error::check_block);
我希望能夠讓這樣的:
if (ec == bc::error::validate)
{
if (ec == bc::error::check_block)
// bc::error::check_block is a more specific case of bc::error::validate
}
看來我可以以某種方式使用類別或條件?我怎麼做,而不需要定義一大堆新的錯誤枚舉?這是一個庫,所以這個庫的用戶必須使用bc :: generic_error :: validate和bc :: error :: check_block。
代碼如下:
#include <system_error>
namespace bc {
enum class error
{
// storage errors
missing_object = 1,
object_already_exists,
unspent_output,
// transaction_pool errors
bad_transaction,
// network errors
resolve_failed,
network_unreachable,
address_in_use,
listen_failed,
accept_failed,
bad_stream,
channel_stopped,
channel_timeout,
// validate
validate_failed,
check_block,
accept_block,
connect_block
};
class error_category_impl
: public std::error_category
{
public:
virtual const char* name() const;
virtual std::string message(int ev) const;
virtual std::error_condition default_error_condition(int ev) const;
};
const std::error_category& error_category();
std::error_code make_error_code(error e);
std::error_condition make_error_condition(error e);
} // bc
namespace std
{
template <>
struct is_error_code_enum<libbitcoin::error>
: public true_type {};
}
而且恩源文件:
#include <bc/error.hpp>
namespace bc {
const char* error_category_impl::name() const
{
return "bitcoin";
}
std::string error_category_impl::message(int ev) const
{
error ec = static_cast<error>(ev);
switch (ec)
{
case error::missing_object:
return "Object does not exist";
case error::object_already_exists:
return "Matching previous object found";
case error::unspent_output:
return "Unspent output";
case error::bad_transaction:
return "Transaction failed to validate";
case error::resolve_failed:
return "Resolving hostname failed";
case error::network_unreachable:
return "Unable to reach remote network";
case error::address_in_use:
return "Address already in use";
case error::listen_failed:
return "Listen incoming connections failed";
case error::accept_failed:
return "Accept connection failed";
case error::bad_stream:
return "Bad stream";
case error::channel_stopped:
return "Channel stopped";
case error::channel_timeout:
return "Channel timed out";
default:
return "Unknown error";
}
}
std::error_condition
error_category_impl::default_error_condition(int ev) const
{
error ec = static_cast<error>(ev);
switch (ec)
{
case error::check_block:
case error::accept_block:
case error::connect_block:
//return error::validate_failed;
return std::errc::permission_denied;
default:
return std::error_condition(ev, *this);
}
}
const std::error_category& error_category()
{
static error_category_impl instance;
return instance;
}
std::error_code make_error_code(error e)
{
return std::error_code(static_cast<int>(e), error_category());
}
std::error_condition make_error_condition(error e)
{
return std::error_condition(static_cast<int>(e), error_category());
}
} // bc
非常有趣!關於如何在C++ 11中實現自定義錯誤消息,現在沒有太多的例子,所以你的答案是非常寶貴的資源。爲了記錄我確實研究了一下你的問題,意識到你必須驗證一個error_condition並將其映射到accept_block/check_block等,但無法確定如何。看到最終在這種情況下,純枚舉比C++ 11枚舉類更好,因爲它們在其名稱空間中具有全局可見性! – 2012-03-19 23:41:12
另外,看到設計得非常好,可以支持像你這樣的中等複雜的錯誤框架,並具有此錯誤代碼分區業務。我只是希望他們在標準化過程中找到了一種方法來簡化系統,但是仍然很難弄清楚它是如何一蹴而就的。 –
2012-03-19 23:52:08
是的,我認爲這是一個很酷的系統:)所有感興趣的源代碼都可以在這裏找到:http://gitorious.org/libbitcoin/libbitcoin/trees/master(參見include/error.hpp和src/error.cpp) – genjix 2012-03-20 12:11:38