Tôi đang sử dụng std :: error_code và có một loạt lỗi được xác định (sử dụng lớp enum) và đã đăng ký.std :: error_code, my_error :: check_block == my_error :: validate && my_error :: accept_block == my_error :: validate
Tôi có lỗi rất chung chung hiện được gọi là my_error :: xác thực, nhưng muốn cung cấp các phiên bản cụ thể hơn trong thư viện của tôi. Nói chung mọi người sẽ muốn sử dụng:
if (ec == bc::error::validate)
// ...
Tuy nhiên đôi khi họ có thể muốn xem các lỗi cụ thể liên quan với điều đó std :: error_code hoặc in các thông báo lỗi.
// ec.message() says "check_block() failed to do XYZ"
assert(ec == bc::error::check_block);
Tôi muốn để có thể cho phép một cái gì đó như:
if (ec == bc::error::validate)
{
if (ec == bc::error::check_block)
// bc::error::check_block is a more specific case of bc::error::validate
}
Có vẻ như tôi bằng cách nào đó có thể sử dụng loại hoặc điều kiện? Làm thế nào tôi có thể làm điều đó mà không cần phải xác định toàn bộ một loạt các enums lỗi mới? Nó cho một thư viện do đó nó sẽ là một nỗi đau cho người dùng của thư viện đó phải sử dụng bc :: generic_error :: validate và bc :: error :: check_block.
Mã là dưới đây:
#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 {};
}
Và TU file nguồn:
#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
Rất thú vị! Hiện tại không có nhiều ví dụ về cách triển khai thông báo lỗi tùy chỉnh trong C++ 11, vì vậy câu trả lời của bạn là một tài nguyên rất có giá trị. Đối với hồ sơ tôi đã nghiên cứu một chút câu hỏi của bạn, nhận ra rằng bạn phải xác nhận một error_condition và bản đồ nó để accept_block/check_block vv nhưng không thể hình dung như thế nào. Nó khá thú vị để thấy rằng cuối cùng trong trường hợp này enum đồng bằng là tốt hơn so với C++ 11 enum lớp chính xác bởi vì họ có khả năng hiển thị toàn cầu trong không gian tên của họ! –
Cũng khá thú vị khi thấy rằng được thiết kế đủ để hỗ trợ một khung lỗi phức tạp vừa phải giống như của bạn, với việc phân đoạn mã lỗi kinh doanh này. Tôi chỉ muốn họ tìm thấy một cách trong quá trình chuẩn hóa để đơn giản hóa hệ thống một chút bằng cách nào đó, nó vẫn thực sự khó để tìm ra cách nó hoạt động ngay từ cái nhìn đầu tiên. –
Vâng, tôi nghĩ rằng đó là một hệ thống khá thú vị :) Mã nguồn có sẵn ở đây cho tất cả các quan tâm: http://gitorious.org/libbitcoin/libbitcoin/trees/master (xem bao gồm/error.hpp và src/error.cpp) – genjix