error_code

Now that we have told the C++ standard library about our custom error code enum err, we actually no longer need to specify EC = err, we can just leave it default to std::error_code:


  result<udt /*, std::error_code */> res(err::failure1);

  // What happens here? What exception type is thrown?
  try
  {
    std::cout << *res.value() << std::endl;
  }
  catch(const std::exception &e)
  {
    // Prints "Exception thrown was failure1", exactly the same as before
    std::cerr << "Exception thrown was " << e.what() << std::endl;
  }
  
View this code on Github

The reason that this works is because std::error_code provides implicit construction from any type with the trait std::is_error_code_enum<> defined to be true, it uses the ADL discovered free function make_error_code() during that implicit construction.

The big advantage of always using EC = std::error_code is that OUTCOME_TRY only works when the EC type is the same (or convertible to) in the try expression as the calling function, so by leaving it at the default of std::error_code, we can use OUTCOME_TRY and save having to type boilerplate:


result<udt> boo()
{
  return err::failure1;
}
result<udt> foo()
{
  OUTCOME_TRY(v, boo());
  return udt{5};  // emplace construct udt with 5
}
View this code on Github