Implicit conversion

Back in The payload, we mentioned that there was no default implicit conversion of file_io_error (status_code<_file_io_error_domain>) to error, as error is too small to hold _file_io_error_domain::value_type.

We can tell the framework about available implicit conversions by defining an ADL discovered free function make_status_code() which takes our custom status code as input, and returns an error:

// Now tell `error` how it can implicitly construct from `file_io_error`.
// This is done by us defining a free function called `make_status_code()`
// which is discovered using ADL. `error` is an alias to the refinement
// `status_code<erased<intptr_t>>` which is a status code whose value type
// has been erased into an `intptr_t`. `status_code<erased<intptr_t>>`
// (i.e. `error`) are move bitcopying (P1029) i.e. they are move-only
// types whose move operation is defined to leave the source in the same
// representation as a default constructed instance, and for whose
// non-trivial destructor when called upon a default constructed instance
// is guaranteed to do nothing.
inline outcome_e::system_code make_status_code(file_io_error v)
{
  // `make_nested_status_code()` dynamically allocates memory to store an
  // instance of `file_io_error`, then returns a status code whose domain
  // specifies that its value type is a pointer to `file_io_error`. The
  // domain is a templated instance which indirects all observers of the
  // status code to the pointed-to status code.
  //
  // Note that the status code returned's value type is a pointer, which
  // by definition fits into `intptr_t` and is trivially copyable.
  // Therefore `system_code` (which is also a type alias to
  // `status_code<erased<intptr_t>>`) is happy to implicitly construct
  // from the status code returned by `make_nested_status_code()`.
  return make_nested_status_code(std::move(v));
}
View this code on Github

We are now ready to use Experimental Outcome!