Created
November 9, 2024 08:54
-
-
Save copyrat90/caf2ea729852b01726ac4e615d684ebd to your computer and use it in GitHub Desktop.
`std::error_code` usage example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <cassert> | |
| #include <iostream> | |
| #include <string> | |
| #include <system_error> | |
| #include <type_traits> | |
| // 온라인 쇼핑몰에서 상품을 구매할 때 발생할 수 있는 오류 | |
| enum PurchaseErrc { | |
| /* 정상 처리 (오류 아님) */ | |
| PE_OK = 0, | |
| /* 판매자 측 오류 */ | |
| PE_STORE_NOT_OPEN = 100, // 상점이 열리지 않은 경우 | |
| PE_OUT_OF_STOCK, // 주문할 제품의 재고가 부족한 경우 | |
| /* 사용자 측 입력 오류 */ | |
| PE_INVALID_ITEMS_AMOUNT = 200, // 잘못된 수량을 입력한 경우 | |
| PE_INVALID_CARD_NUMBER, // 잘못된 카드 번호를 입력한 경우 | |
| /* 쇼핑몰 측 오류 */ | |
| PE_INTERNAL_ERROR = 5000, // 쇼핑몰 측 내부 오류 | |
| }; | |
| // 온라인 쇼핑몰에 상품을 등록할 때 발생할 수 있는 오류 | |
| enum RegisterProductErrc { | |
| /* 정상 처리 (오류 아님) */ | |
| RPE_OK = 0, | |
| /* 사용자 측 입력 오류 */ | |
| RPE_INVALID_STOCK_AMOUNT = 5000, // 잘못된 재고량을 입력한 경우 | |
| RPE_NO_NAME_PROVIDED, // 상품 이름을 입력하지 않은 경우 | |
| /* 쇼핑몰 측 오류 */ | |
| RPE_INTERNAL_ERROR = 9999, // 쇼핑몰 측 내부 오류 | |
| }; | |
| enum FailReasonErrc { | |
| /* 오류값은 `0`이 아님에 유의 */ | |
| FRE_SELLER_NOT_READY = 1, // 판매자 측 오류 | |
| FRE_BAD_USER_INPUT, // 사용자 측 입력 오류 | |
| FRE_SYSTEM_ERROR, // 쇼핑몰 측 오류 | |
| }; | |
| namespace std { | |
| // 1. `value`를 `true`로 직접 설정 | |
| template <> | |
| struct is_error_code_enum<PurchaseErrc> { | |
| static constexpr bool value = true; | |
| }; | |
| // 2. 같은 일을 하는 `std::true_type` 상속받기 | |
| template <> | |
| struct is_error_code_enum<RegisterProductErrc> : true_type {}; | |
| // `std::error_condition`용 enum | |
| template <> | |
| struct is_error_condition_enum<FailReasonErrc> : true_type {}; | |
| } | |
| struct PurchaseErrorCategory : std::error_category { | |
| static auto instance() -> const PurchaseErrorCategory& { | |
| static PurchaseErrorCategory category; | |
| return category; | |
| } | |
| auto name() const noexcept -> const char* override { | |
| return "Purchase"; | |
| } | |
| auto message(int ev) const -> std::string override { | |
| switch (static_cast<PurchaseErrc>(ev)) { | |
| case PurchaseErrc::PE_OK: | |
| return "OK"; | |
| case PurchaseErrc::PE_STORE_NOT_OPEN: | |
| return "Store not open"; | |
| case PurchaseErrc::PE_OUT_OF_STOCK: | |
| return "Item out of stock"; | |
| case PurchaseErrc::PE_INVALID_ITEMS_AMOUNT: | |
| return "Invalid items count provided"; | |
| case PurchaseErrc::PE_INVALID_CARD_NUMBER: | |
| return "Invalid card number provided"; | |
| case PurchaseErrc::PE_INTERNAL_ERROR: | |
| return "Internal system error"; | |
| default: | |
| return "(Unknown error)"; | |
| } | |
| } | |
| auto default_error_condition(int ev) const noexcept -> std::error_condition { | |
| if (ev % 100 == 1) // 100번대 오류 | |
| return FailReasonErrc::FRE_SELLER_NOT_READY; | |
| else if (ev % 100 == 2) // 200번대 오류 | |
| return FailReasonErrc::FRE_BAD_USER_INPUT; | |
| else if (ev == static_cast<int>(PurchaseErrc::PE_INTERNAL_ERROR)) | |
| return FailReasonErrc::FRE_SYSTEM_ERROR; | |
| else | |
| assert(false); | |
| return {}; | |
| } | |
| private: | |
| PurchaseErrorCategory() = default; | |
| }; | |
| auto make_error_code(PurchaseErrc e) -> std::error_code { | |
| return std::error_code(static_cast<int>(e), PurchaseErrorCategory::instance()); | |
| } | |
| struct RegisterProductErrorCategory : std::error_category { | |
| static auto instance() -> const RegisterProductErrorCategory& { | |
| static RegisterProductErrorCategory category; | |
| return category; | |
| } | |
| auto name() const noexcept -> const char* override { | |
| return "RegisterProduct"; | |
| } | |
| auto message(int ev) const -> std::string override { | |
| switch (static_cast<RegisterProductErrc>(ev)) { | |
| case RegisterProductErrc::RPE_OK: | |
| return "OK"; | |
| case RegisterProductErrc::RPE_INVALID_STOCK_AMOUNT: | |
| return "Invalid stock amount provided"; | |
| case RegisterProductErrc::RPE_NO_NAME_PROVIDED: | |
| return "No item name provided"; | |
| case RegisterProductErrc::RPE_INTERNAL_ERROR: | |
| return "Internal system error"; | |
| default: | |
| return "(Unknown error)"; | |
| } | |
| } | |
| private: | |
| RegisterProductErrorCategory() = default; | |
| }; | |
| auto make_error_code(RegisterProductErrc e) -> std::error_code { | |
| return std::error_code(static_cast<int>(e), RegisterProductErrorCategory::instance()); | |
| } | |
| struct FailReasonErrorCategory : std::error_category { | |
| static auto instance() -> const FailReasonErrorCategory& { | |
| static FailReasonErrorCategory category; | |
| return category; | |
| } | |
| auto name() const noexcept -> const char* override { | |
| return "FailReason"; | |
| } | |
| auto message(int ev) const -> std::string override { | |
| switch (static_cast<FailReasonErrc>(ev)) { | |
| case FailReasonErrc::FRE_SELLER_NOT_READY: | |
| return "Seller is not ready"; | |
| case FailReasonErrc::FRE_BAD_USER_INPUT: | |
| return "Bad user input provided"; | |
| case FailReasonErrc::FRE_SYSTEM_ERROR: | |
| return "Internal system error"; | |
| default: | |
| return "(Unknown error)"; | |
| } | |
| } | |
| bool equivalent(const std::error_code& code, int condition_value) const noexcept override { | |
| const std::error_category& purchase_category = PurchaseErrorCategory::instance(); | |
| const std::error_category& register_product_category = RegisterProductErrorCategory::instance(); | |
| switch (static_cast<FailReasonErrc>(condition_value)) { | |
| case FailReasonErrc::FRE_SELLER_NOT_READY: | |
| if (code.category() == purchase_category) | |
| return code.value() / 100 == 1; // 100번대 오류 | |
| return false; | |
| case FailReasonErrc::FRE_BAD_USER_INPUT: | |
| if (code.category() == purchase_category) | |
| return code.value() / 100 == 2; // 200번대 오류 | |
| else if (code.category() == register_product_category) | |
| return code.value() / 1000 == 5; // 5000번대 오류 | |
| return false; | |
| case FailReasonErrc::FRE_SYSTEM_ERROR: | |
| return code == PurchaseErrc::PE_INTERNAL_ERROR || | |
| code == RegisterProductErrc::RPE_INTERNAL_ERROR; | |
| default: | |
| break; | |
| } | |
| return false; | |
| } | |
| private: | |
| FailReasonErrorCategory() = default; | |
| }; | |
| auto make_error_condition(FailReasonErrc e) -> std::error_condition { | |
| return std::error_condition(static_cast<int>(e), FailReasonErrorCategory::instance()); | |
| } | |
| int main() { | |
| std::error_code ec = PurchaseErrc::PE_OUT_OF_STOCK; | |
| assert(ec != RegisterProductErrc::RPE_INTERNAL_ERROR); | |
| std::cout << "[" << ec << "] " << ec.message() << std::endl; | |
| ec = RegisterProductErrc::RPE_NO_NAME_PROVIDED; | |
| assert(ec == RegisterProductErrc::RPE_NO_NAME_PROVIDED); | |
| std::cout << "[" << ec << "] " << ec.message() << std::endl; | |
| ec = PurchaseErrc::PE_INVALID_CARD_NUMBER; | |
| assert(ec == FailReasonErrc::FRE_BAD_USER_INPUT); | |
| std::cout << "[" << ec << "] " << ec.message() << std::endl; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment