1+++ 2title = "`basic_outcome<T, EC, EP, NoValuePolicy>`" 3description = "A type carrying one of (i) a successful `T` (ii) a disappointment `EC` (iii) a failure `EP` (iv) both a disappointment `EC` and a failure `EP`, with `NoValuePolicy` specifying what to do if one tries to read state which isn't there." 4+++ 5 6A type carrying one of (i) a successful `T` (ii) a disappointment `EC` (iii) a failure `EP` (iv) both a disappointment `EC` and a failure `EP`, with `NoValuePolicy` specifying what to do if one tries to read state which isn't there. Any one, two, or all of `T`, `EC` and `EP` can be `void` to indicate no value for that state is present. Detectable using {{% api "is_basic_outcome<T>" %}}. 7 8*Requires*: Concept requirements if C++ 20, else static asserted: 9 10- That trait {{% api "type_can_be_used_in_basic_result<R>" %}} is true for `T`, `EC` and `EP`. 11- That either `EC` is `void` or `DefaultConstructible`. 12- That either `EP` is `void` or `DefaultConstructible`. 13 14*Namespace*: `BOOST_OUTCOME_V2_NAMESPACE` 15 16*Header*: `<boost/outcome/basic_outcome.hpp>` 17 18*Inclusions*: The very lightest weight of C and C++ header files: 19 201. `<cstdint>` 212. `<initializer_list>` 223. `<iosfwd>` 234. `<new>` 245. `<type_traits>` 256. If {{% api "BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE" %}} is `1`, `<utility>` (defaults to `1` for C++ 17 or later only) 267. If C++ exceptions disabled and `BOOST_OUTCOME_DISABLE_EXECINFO` undefined only (used to print stack backtraces on "exception throw"): 27 1. `<sal.h>` (Windows only) 28 2. `<stddef.h>` (Windows only) 29 3. `<string.h>` (Windows only) 30 4. `<execinfo.h>` (POSIX only) 318. `<cstdio>` 329. `<cstdlib>` 3310. `<cassert>` 34 35This very light weight set of inclusion dependencies makes basic outcome suitable for use in global header files of very large C++ codebases. 36 37### Design rationale 38 39`basic_outcome` extends {{% api "basic_result<T, E, NoValuePolicy>" %}} with a third state to transport, 40conventionally (but not necessarily) some sort of "abort" or "exceptional" state which a function can 41return to indicate that not only did the operation fail, but it did so *catastrophically* i.e. please 42abort any attempt to retry the operation. 43 44A perfect alternative is to throw a C++ exception for the abort code path, and indeed most programs 45ought to do exactly that instead of using `basic_outcome`. However there are a number of use cases 46where choosing `basic_outcome` shines: 47 481. Where C++ exceptions or RTTI is not available, but the ability to fail catastrophically without 49terminating the program is important. 502. Where deterministic behaviour is required even in the catastrophic failure situation. 513. In unit test suites of code using Outcome it is extremely convenient to accumulate test failures 52into a `basic_outcome` for later reporting. A similar convenience applies to RPC situations, where 53C++ exception throws need to be accumulated for reporting back to the initiating endpoint. 544. Where a function is "dual use deterministic" i.e. it can be used deterministically, in which case 55one switches control flow based on `.error()`, or it can be used non-deterministically by throwing 56an exception perhaps carrying a custom payload. 57 58### Public member type aliases 59 60- `value_type` is `T`. 61- `error_type` is `EC`. 62- `exception_type` is `EP`. 63- `value_type_if_enabled` is `T` if construction from `T` is available, else it is a usefully named unusable internal type. 64- `error_type_if_enabled` is `EC` if construction from `EC` is available, else it is a usefully named unusable internal type. 65- `exception_type_if_enabled` is `EP` if construction from `EP` is available, else it is a usefully named unusable internal type. 66- `rebind<A, B = EC, C = EP, D = NoValuePolicy>` is `basic_outcome<A, B, C, D>`. 67 68### Protected member predicate booleans 69 70- `predicate::constructors_enabled` is constexpr boolean true if: 71 1. Decayed `value_type` and decayed `error_type` are not the same type, or both are `void`. 72 2. Decayed `value_type` and decayed `exception_type` are not the same type, or both are `void`. 73 3. Decayed `error_type` and decayed `exception_type` are not the same type, or both are `void`. 74 75- `predicate::implicit_constructors_enabled` is constexpr boolean true if: 76 1. `predicate::constructors_enabled` is true. 77 2. Trait {{% api "is_error_type<E>" %}} is not true for both decayed `value_type` and decayed `error_type` at the same time. 78 3. `value_type` is not implicitly constructible from `error_type` and `error_type` is not implicitly constructible from `value_type`.<br>OR<br>trait {{% api "is_error_type<E>" %}} is true for decayed `error_type` and `error_type` is not implicitly constructible from `value_type` and `value_type` is an integral type. 79 4. `value_type` is not implicitly constructible from `exception_type`. 80 5. `error_type` is not implicitly constructible from `exception_type`. 81 6. `exception_type` is not implicitly constructible from `value_type`. 82 7. `exception_type` is not implicitly constructible from `error_type`. 83 84- `predicate::enable_value_converting_constructor<A>` is constexpr boolean true if: 85 1. `predicate::constructors_enabled` is true. 86 2. Decayed `A` is not this `basic_outcome` type. 87 3. `predicate::implicit_constructors_enabled` is true. 88 4. Decayed `A` is not an `in_place_type_t`. 89 5. Trait {{% api "is_error_type_enum<E, Enum>" %}} is false for `error_type` and decayed `A`. 90 6. `value_type` is implicitly constructible from `A` and `error_type` is not implicitly constructible from `A`.<br>OR<br>`value_type` is the exact same type as decayed `A` and `value_type` is implicitly constructible from `A`. 91 7. `exception_type` is not implicitly constructible from `A`. 92 93- `predicate::enable_error_converting_constructor<A>` is constexpr boolean true if: 94 1. `predicate::constructors_enabled` is true. 95 2. Decayed `A` is not this `basic_outcome` type. 96 3. `predicate::implicit_constructors_enabled` is true. 97 4. Decayed `A` is not an `in_place_type_t`. 98 5. Trait {{% api "is_error_type_enum<E, Enum>" %}} is false for `error_type` and decayed `A`. 99 6. `value_type` is not implicitly constructible from `A` and `error_type` is implicitly constructible from `A`.<br>OR<br>`error_type` is the exact same type as decayed `A` and `error_type` is implicitly constructible from `A`. 100 7. `exception_type` is not implicitly constructible from `A`. 101 102- `predicate::enable_error_condition_converting_constructor<ErrorCondEnum>` is constexpr boolean true if: 103 1. `predicate::constructors_enabled` is true. 104 2. Decayed `ErrorCondEnum` is not this `basic_outcome` type. 105 3. Decayed `ErrorCondEnum` is not an `in_place_type_t`. 106 4. Trait {{% api "is_error_type_enum<E, Enum>" %}} is true for `error_type` and decayed `ErrorCondEnum`. 107 5. `exception_type` is not implicitly constructible from `ErrorCondEnum`. 108 109- `predicate::enable_exception_converting_constructor<A>` is constexpr boolean true if: 110 1. `predicate::constructors_enabled` is true. 111 2. Decayed `A` is not this `basic_outcome` type. 112 3. `predicate::implicit_constructors_enabled` is true. 113 4. Decayed `A` is not an `in_place_type_t`. 114 5. `value_type` is not implicitly constructible from `A`. 115 6. `error_type` is not implicitly constructible from `A`. 116 7. `exception_type` is implicitly constructible from `A`. 117 118- `predicate::enable_error_exception_converting_constructor<A, B>` is constexpr boolean true if: 119 1. `predicate::constructors_enabled` is true. 120 2. Decayed `A` is not this `basic_outcome` type. 121 3. `predicate::implicit_constructors_enabled` is true. 122 4. Decayed `A` is not an `in_place_type_t`. 123 5. `value_type` is not implicitly constructible from `A`. 124 6. `error_type` is implicitly constructible from `A`. 125 7. `value_type` is not implicitly constructible from `B`. 126 8. `exception_type` is implicitly constructible from `B`. 127 128- `predicate::enable_compatible_conversion<A, B, C, D>` is constexpr boolean true if: 129 1. `predicate::constructors_enabled` is true. 130 2. `basic_outcome<A, B, C, D>` is not this `basic_outcome` type. 131 3. `A` is `void` OR `value_type` is explicitly constructible from `A`. 132 4. `B` is `void` OR `error_type` is explicitly constructible from `B`. 133 5. `C` is `void` OR `exception_type` is explicitly constructible from `C`. 134 135- `predicate::enable_make_error_code_compatible_conversion<A, B, C, D>` is constexpr boolean true if: 136 1. `predicate::constructors_enabled` is true. 137 2. `basic_outcome<A, B, C, D>` is not this `basic_outcome` type. 138 3. Trait {{% api "is_error_code_available<E>" %}} is true for decayed `error_type`. 139 4. `predicate::enable_compatible_conversion<A, B, C, D>` is not true. 140 5. `A` is `void` OR `value_type` is explicitly constructible from `A`. 141 6. `error_type` is explicitly constructible from `make_error_code(B)`. 142 7. `C` is `void` OR `exception_type` is explicitly constructible from `C`. 143 144- `predicate::enable_inplace_value_constructor<Args...>` is constexpr boolean true if: 145 1. `predicate::constructors_enabled` is true. 146 2. `value_type` is `void` OR `value_type` is explicitly constructible from `Args...`. 147 148- `predicate::enable_inplace_error_constructor<Args...>` is constexpr boolean true if: 149 1. `predicate::constructors_enabled` is true. 150 2. `error_type` is `void` OR `error_type` is explicitly constructible from `Args...`. 151 152- `predicate::enable_inplace_exception_constructor<Args...>` is constexpr boolean true if: 153 1. `predicate::constructors_enabled` is true. 154 2. `exception_type` is `void` OR `exception_type` is explicitly constructible from `Args...`. 155 156- `predicate::enable_inplace_value_error_exception_constructor<Args...>` is constexpr boolean true if: 157 1. `predicate::constructors_enabled` is true. 158 2. `predicate::implicit_constructors_enabled` is true. 159 3. Exactly one of `value_type` is explicitly constructible from `Args...`, or `error_type` is explicitly constructible from `Args...`, or `exception_type` is explicitly constructible 160 from `Args...`. 161 162#### Summary of [standard requirements provided](https://en.cppreference.com/w/cpp/named_req) 163 164- ~~`DefaultConstructible`~~, always deleted to force user to choose valued or errored or excepted for every outcome instanced. 165- `MoveConstructible`, if all of `value_type`, `error_type` and `exception_type` implement move constructors. 166- `CopyConstructible`, if all of `value_type`, `error_type` and `exception_type` implement copy constructors. 167- `MoveAssignable`, if all of `value_type`, `error_type` and `exception_type` implement move constructors and move assignment. 168- `CopyAssignable`, if all of `value_type`, `error_type` and `exception_type` implement copy constructors and copy assignment. 169- `Destructible`. 170- `TriviallyCopyable`, if all of `value_type`, `error_type` and `exception_type` are trivially copyable. 171- `TrivialType`, if all of `value_type`, `error_type` and `exception_type` are trivial types. 172- `LiteralType`, if all of `value_type`, `error_type` and `exception_type` are literal types. 173- ~~`StandardLayoutType`~~. It is implementation defined if `basic_outcome` can be used by C. 174However all of the three major compilers MSVC, GCC and clang implement C layout of `basic_outcome` as follows: 175 176 ```c++ 177 struct outcome_layout { 178 struct result_layout { 179 value_type value; 180 unsigned int flags; 181 error_type error; 182 }; 183 exception_type exception; 184 }; 185 ``` 186 If you choose standard layout `value_type`, `error_type` and `exception_type`, `basic_outcome` 187works fine from C on MSVC, GCC and clang. 188- `EqualityComparable`, if all of `value_type`, `error_type` and `exception_type` implement equality comparisons with one another. 189- ~~`LessThanComparable`~~, not implemented due to availability of implicit conversions from `value_type`, `error_type` and `exception_type`, this can cause major surprise (i.e. hard to diagnose bugs), so we don't implement these at all. 190~ `Swappable` 191- ~~`Hash`~~, not implemented as a generic implementation of a unique hash for non-valued items which are unequal would require a dependency on RTTI being enabled. 192 193Thus `basic_outcome` meets the `Regular` concept if all of `value_type`, `error_type` and `exception_type` are `Regular`, except for the lack of a default constructor. Often where one needs a default constructor, wrapping `basic_outcome` into {{% api "std::optional<T>" %}} will suffice. 194 195### Public member functions 196 197#### Disabling constructors 198 199{{% children description="true" depth="2" categories="disabling-constructors" %}} 200 201#### Copy and move constructors and assignment, and destructor 202 203{{% children description="true" depth="2" categories="default-constructors,copy-constructors,move-constructors,copy-assignment,move-assignment,destructors" %}} 204 205#### Converting constructors 206 207{{% children description="true" depth="2" categories="converting-constructors" %}} 208 209#### Inplace constructors 210 211{{% children description="true" depth="2" categories="inplace-constructors" %}} 212 213#### Tagged constructors 214 215{{% children description="true" depth="2" categories="tagged-constructors" %}} 216 217#### Observers 218 219{{% children description="true" depth="2" categories="observers" %}} 220 221#### Modifiers 222 223{{% children description="true" depth="2" categories="modifiers" %}} 224 225#### Comparisons 226 227See above for why `LessThanComparable` is not implemented. 228 229{{% children description="true" depth="2" categories="comparisons" %}} 230 231