Skip to content

Instantly share code, notes, and snippets.

@copyrat90
Created November 9, 2024 08:54
Show Gist options
  • Select an option

  • Save copyrat90/caf2ea729852b01726ac4e615d684ebd to your computer and use it in GitHub Desktop.

Select an option

Save copyrat90/caf2ea729852b01726ac4e615d684ebd to your computer and use it in GitHub Desktop.
`std::error_code` usage example
#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