2012-03-18 15 views
7

Std :: error_code kullanıyorum ve bir hata tanımladım (enum sınıfını kullanarak) ve kayıtlı. std :: error_code, my_error :: check_block == my_error :: validate && my_error :: accept_block == my_error :: validate

Şimdi my_error denilen :: doğrulamak çok genel bir hata var, ama benim kütüphanede daha belirgin versiyonlarını sağlamak istiyoruz. Genelde insanlar kullanmak isteyeceklerdir:

if (ec == bc::error::validate) 
    // ... 

Ancak bazen bu std :: Error_Code ilişkili belirli hata görebilirsiniz veya hata mesajı yazdırmak isteyebilirsiniz. Ben nasılsa kategorileri veya koşulları kullanabilirsiniz görünüyor

if (ec == bc::error::validate) 
{ 
    if (ec == bc::error::check_block) 
     // bc::error::check_block is a more specific case of bc::error::validate 
} 

:

// ec.message() says "check_block() failed to do XYZ" 
assert(ec == bc::error::check_block); 

ben gibi bir şey etkinleştirmek için isterler? Bir sürü yeni hata enumunu tanımlamaya gerek kalmadan bunu nasıl yapabilirim? Bir kütüphane için bu kütüphanenin kullanıcısı için bc :: generic_error :: validate ve bc :: error :: check_block kullanmak zorunda kalması bir acı olur.

#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 {}; 
} 

Ve TU kaynak dosyası:

Kod altındadır

#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 

cevap

9

Tamam ben boost yardım :: asio ve std :: hata_kodu yaratıcısı var ve kendini usta: Chris Kohlhoff . ADL kullanırken

, başparmak iyi bir kural herhangi eleme (benim durumumda hata :: error_code_t) gerekmez ve ben yanlış kapsamında olmasıdır.

#include <iostream> 
#include <system_error> 

namespace libbitcoin { 

namespace error 
{ 
    // Specific errors 
    enum error_code_t 
    { 
     // 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 
     check_block, 
     accept_block, 
     connect_block 
    }; 

    // error_condition 
    enum error_condition_t 
    { 
     // validate 
     validate_failed = 1 
    }; 

    std::error_code make_error_code(error_code_t e); 
    std::error_condition make_error_condition(error_condition_t e); 
} 

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(); 

} // libbitcoin 

namespace std 
{ 
    template <> 
    struct is_error_code_enum<libbitcoin::error::error_code_t> 
     : public true_type {}; 

    template <> 
    struct is_error_condition_enum<libbitcoin::error::error_condition_t> 
     : public true_type {}; 
} 

// ------------------------------------------------------------------- 

namespace libbitcoin { 

namespace error { 
std::error_code make_error_code(error_code_t e) 
{ 
    return std::error_code(static_cast<int>(e), error_category()); 
} 

std::error_condition make_error_condition(error_condition_t e) 
{ 
    return std::error_condition(static_cast<int>(e), error_category()); 
} 
} 

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 (ev) 
    { 
     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"; 
     case error::check_block: 
      return "Checkblk"; 
     default: 
      return "Unknown error"; 
    } 
} 

std::error_condition 
    error_category_impl::default_error_condition(int ev) const 
{ 
    //error ec = static_cast<error>(ev); 
    switch (ev) 
    { 
     case error::check_block: 
     case error::accept_block: 
     case error::connect_block: 
      return std::error_condition(error::validate_failed, *this); 
     default: 
      return std::error_condition(ev, *this); 
    } 
} 

const std::error_category& error_category() 
{ 
    static error_category_impl instance; 
    return instance; 
} 

} // libbitcoin 

using namespace libbitcoin; 

#include <assert.h> 

int main() 
{ 
    std::error_code ec = error::check_block; 
    assert(ec == error::validate_failed); 
    assert(ec == error::check_block); 
    std::cout << ec.message() << std::endl; 
    //ec = error::missing_object; 
    return 0; 
} 
+2

Çok ilginç! Şu anda C++ 11'de özel hata mesajının nasıl uygulanacağı konusunda pek fazla örnek yok, dolayısıyla cevabınız çok değerli bir kaynak. Kayıt için ben biraz soru çalışılan bir error_condition doğrulamak yapmak ve/check_block vb accept_block eşlemek zorunda ama nasıl çözemedim fark etmedi. Bu durumda en sonunda düz enumun C++ 11 enum sınıfından daha iyi olduğunu görmekten oldukça zevkliydi çünkü onların adlarında global görünürlükleri var! –

+0

Ayrıca bu hata kodu bölümleme iş ile, yani yeterince iyi sizinki gibi bir orta karmaşık hata çerçevesini destekleyecek şekilde tasarlanmıştır görmek oldukça serin. Sistemin basitleştirilmesi için standardizasyonun bir yolunu bulduklarını keşfettim, bir şekilde daha ilk bakışta nasıl çalıştığını anlamak gerçekten zor. –

+1

Evet, bence oldukça havalı bir sistem :) Kaynak kodu tüm ilgililer için burada mevcuttur: http://gitorious.org/libbitcoin/libbitcoin/trees/master (bkz. Include/error.hpp ve src/error.cpp) hatta daha ince taneli hatalar içine şimdi ayrılmışlar hata :: check_block ve hata :: validate_block eşdeğerdir bir hata :: check_block kategorisine bu hatalara takma nasılsa iyi olurdu: – genjix

İlgili konular