• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1+++
2title = "`status_result` and `status_outcome`"
3weight = 40
4+++
5
6`status_result` and `status_outcome` are type aliases to {{< api "basic_result<T, E, NoValuePolicy>" >}}
7and {{< api "basic_outcome<T, EC, EP, NoValuePolicy>" >}} in the usual way, but
8with a defaulted `NoValuePolicy` which selects on the basis of `status_code<DomainType>`
9instead.
10
11{{% notice note %}}
12If the `E` type is not some `status_code<>`, the default policy selector
13will complain.
14{{% /notice %}}
15
16The specifications are:
17
18```c++
19experimental::status_result<T, E = experimental::system_code>
20experimental::status_outcome<T, E = experimental::system_code, EP = std::exception_ptr>
21```
22
23So, the default `E` is the erased status code `system_code`, which can represent
24any `generic_code`, `posix_code`, `win32_code`, `nt_code`, `com_code` and many
25other integer error and status
26codings. **Note** that `system_code` may represent successes as well as failures.
27This mirrors, somewhat, how `std::error_code` can have an all bits zero defaulted
28state.
29
30You can absolutely choose an `E` type which is non-erased e.g. `posix_code` directly.
31You can also choose an `E` type which is contract guaranteed to be a failure
32rather than an unknown success or failure -- see `errored_status_code`.
33
34Whether to choose typed status codes versus the erased status codes depends on your
35use cases. Outcome replicates faithfully the implicit and explicit conversion
36semantics of its underlying types, so you can mix results and outcomes of
37`<system_error2>` types exactly as you can the `<system_error2>` types themselves
38e.g. typed forms will implicitly convert into erased forms if the source type
39is trivially copyable or move relocating. This means that you can return a
40`generic_code` from a function returning a `system_code` or `error`, and it'll
41work exactly as you'd expect (implicit conversion).
42
43{{% notice note %}}
44As `status_code<erased<T>>` is move-only, so is any `status_result` or `status_outcome`.
45For some reason this surprises a lot of people, and they tend to react by not using the erased
46form because it seems "difficult".
47{{% /notice %}}
48
49It is actually, in fact, a wise discipline to follow to make all functions return
50move-only types if you care about determinism and performance. Whilst C++ 17 onwards
51does much to have the compiler avoid copying of identical function return values thanks to
52guaranteed copy elision, when a chain of functions return different types, if the
53programmer forgets to scatter `std::move()` appropriately, copies rather than moves
54tend to occur in non-obvious ways. No doubt future C++ standards will improve on the
55automatic use of moves instead of copies where possible, but until then making all
56your `result` and `outcome` types move-only is an excellent discipline.
57
58Note that move-only `result` and `outcome` capable code (i.e. your project is in Experimental
59Outcome configuration) usually compiles fine when `result` and `outcome` are copyable
60(i.e. your project is in Standard Outcome configuration), albeit sometimes with a few
61compiler warnings about unnecessary use of `std::move()`.
62