fork download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <map>
  4.  
  5. template <typename E>
  6. struct enum_traits
  7. {
  8. static const char* const name;
  9. static const std::map<E, std::string> mapping;
  10. };
  11.  
  12. template <typename E>
  13. struct ECategory_impl : std::error_category
  14. {
  15. static_assert(std::is_enum<E>::value, "!");
  16.  
  17. const char* name() const noexcept override
  18. {
  19. return enum_traits<E>::name;
  20. }
  21.  
  22. std::string message(int c) const override
  23. {
  24. const auto& Map = enum_traits<E>::mapping;
  25. E code = static_cast<E>(c);
  26. auto itr = Map.find(code);
  27. if (itr != Map.end())
  28. {
  29. return itr->second;
  30. }
  31. else
  32. {
  33. return "(unrecognized error)";
  34. }
  35. }
  36. };
  37.  
  38. template <typename E>
  39. std::error_code make_error_code(E e)
  40. {
  41. static_assert(std::is_enum<E>::value, "!");
  42. static const ECategory_impl<E> categ{};
  43. return {static_cast<int>(e), categ};
  44. }
  45.  
  46. #define MAKE_ERROR_CODE_CATEGORY(E) \
  47.   template <> const char* const enum_traits<E>::name = #E; \
  48. namespace std \
  49. { \
  50.   template <> \
  51.   struct is_error_code_enum<E> : true_type {}; \
  52. } \
  53. using E##_category = ECategory_impl<E>;
  54.  
  55. enum class E {A, B};
  56. template <> const std::map<E, std::string> enum_traits<E>::mapping
  57. {
  58. {E::A, "A"},
  59. {E::B, "E::B"}
  60. };
  61.  
  62. MAKE_ERROR_CODE_CATEGORY(E)
  63.  
  64. int main()
  65. {
  66. auto ec = make_error_code(E::A);
  67. static_cast<void>(ec);
  68. }
  69.  
Success #stdin #stdout 0s 4472KB
stdin
Standard input is empty
stdout
Standard output is empty