-- What happens?

Let us run the code from the previous page:

ned@lyta:~/outcome/build_posix$ bin/outcome-snippets_error_code_enums1
Segmentation fault (core dumped)
ned@lyta:~/outcome/build_posix$

Also undefined behaviour. This is because Outcome doesn’t know what to do with a strongly typed enum any more than some user defined struct.

Let us register our error code enum with the C++ standard library. This causes Outcome to treat it quite differently.


struct udt
{
  int a{0};
  explicit udt(int _a)
      : a(_a)
  {
  }
  udt() = default;
  int operator*() const { return a; }
};
enum class err
{
  success,
  failure1,
  failure2
};

// Tell the standard library that enum err is an error code enum
// by specialising the is_error_code_enum trait. See
// http://en.cppreference.com/w/cpp/error/error_code/is_error_code_enum
namespace std
{
  template <> struct is_error_code_enum<err> : std::true_type
  {
  };
}

// We also must declare a free function make_error_code. This is
// discovered via ADL by the standard library. See
// http://en.cppreference.com/w/cpp/error/errc/make_error_code
inline std::error_code make_error_code(err c)
{
  // We need to inherit from std::error_category to define
  // an error code domain with the standard library for
  // our strongly typed enum. See
  // http://en.cppreference.com/w/cpp/error/error_category
  static struct err_category : std::error_category
  {
    virtual const char *name() const noexcept override final { return "err_category"; };
    virtual std::string message(int c) const override final
    {
      switch(static_cast<err>(c))
      {
      case err::success:
        return "err::success";
      case err::failure1:
        return "err::failure1";
      case err::failure2:
        return "err::failure2";
      }
      return "unknown";
    }
  } category;
  return std::error_code(static_cast<int>(c), category);
}
View this code on Github