2012-03-18 21 views
7

मान्य करें मैं std :: error_code का उपयोग कर रहा हूं और त्रुटि की परिभाषा का एक गुच्छा है (एनम क्लास का उपयोग करके) और दर्ज कराई।std :: error_code, my_error :: check_block == my_error :: मान्य करें && my_error :: accept_block == my_error ::

मेरे पास अब बहुत ही सामान्य त्रुटि है जिसे my_error :: मान्य है, लेकिन मेरी लाइब्रेरी में अधिक विशिष्ट संस्करण प्रदान करना चाहते हैं। हालांकि कभी कभी वे विशिष्ट है कि std :: error_code त्रुटि के साथ जुड़े त्रुटि देख या त्रुटि संदेश मुद्रित करने के लिए इच्छा हो सकती है

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

: आम तौर पर लोगों को उपयोग करने के लिए चाहते हैं।

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

मैं की तरह कुछ सक्षम करने के लिए सक्षम होना चाहते हैं? मैं नई त्रुटि enums के पूरे समूह को परिभाषित करने के बिना यह कैसे कर सकता हूं? यह एक पुस्तकालय के लिए है, इसलिए यह पुस्तकालय के उपयोगकर्ता के लिए बीसी :: जेनेरिक_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 

उत्तर

9

ठीक मैं बढ़ावा से मदद :: asio और std :: error_code त्रुटि निर्माता मिल गया और खुद को गुरु: क्रिस Kohlhoff ।

एडीएल का उपयोग करते समय, अंगूठे का एक अच्छा नियम यह है कि इसे किसी भी योग्यता (त्रुटि :: error_code_t मेरे मामले में) की आवश्यकता नहीं है, और मैं गलत दायरे में था।

#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

बहुत रोचक! C++ 11 में कस्टम त्रुटि संदेश को कार्यान्वित करने के तरीके पर अभी बहुत अधिक उदाहरण नहीं हैं, इसलिए आपका उत्तर एक बहुत ही मूल्यवान संसाधन है। रिकॉर्ड के लिए मैंने आपके प्रश्न का थोड़ा सा अध्ययन किया, एहसास हुआ कि आपको एक त्रुटि_condition मान्य करना है और इसे स्वीकार_block/check_block आदि पर मैप करना है, लेकिन यह नहीं समझ सका। यह देखने में काफी मनोरंजक है कि अंत में इस मामले में सादा enum सी ++ 11 एनम कक्षा से बेहतर है क्योंकि उनके पास उनके नामस्थान में वैश्विक दृश्यता है! –

+0

यह भी देखने के लिए काफी अच्छा है कि इस त्रुटि कोड विभाजन व्यवसाय के साथ आपके जैसे मामूली जटिल त्रुटि ढांचे का समर्थन करने के लिए पर्याप्त रूप से डिज़ाइन किया गया है। मेरी इच्छा है कि उन्हें किसी भी तरह से सिस्टम को थोड़ा सा सरल बनाने के लिए मानकीकरण के दौरान एक रास्ता मिल गया, फिर भी यह पता लगाना अभी भी मुश्किल है कि यह पहली नजर में कैसे काम करता है। –

+1

हाँ, मुझे लगता है कि यह एक बहुत अच्छी प्रणाली है :) स्रोत कोड सभी रुचि के लिए यहां उपलब्ध है: http://gitorious.org/libbitcoin/libbitcoin/trees/master (देखें/error.hpp और src/error.cpp शामिल करें) – genjix