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));
}
We are now ready to use Experimental Outcome!