3rdParty/boost/1.78.0/libs/outcome/doc/html/experimental/differences.html
The major design differences between and proposed are as follows:
experimental::status_code<DomainType> can represent warnings and form-of-success codes as well as failure codes. experimental::errored_status_code<DomainType> is more similar to std::error_code, in that it can only represent failures (this is enforced by C++ 20 contract or runtime assertion check).
The code’s domain implementation defines the payload type to be transported around by experimental::status_code<DomainType>, rather than it being hardcoded to int as in std::error_code. The payload type can be anything you like, including non-trivially-copyable, move-only, complex etc types.
If your domain defines a payload type which is trivially copyable or move relocating1, it gains an implicit convertibility to a move-only experimental::status_code<erased<T>> where T is another trivially copyable or move relocating type. This permits global headers to use a single, common, type erased, status code type which is highly desirable for code bases of any complexity. However, unlike std::error_code, which fulfils the exact same role in `` based code, the type erased payload can be bigger than the hardcoded int in std::error_code.
Equality comparisons between status code’s with non-identical domains are always semantic i.e. are they semantically equivalent, rather than exactly equal? This mirrors when you compare std::error_code to a std::error_condition, but as there is no equivalent for the latter in ``, this means that when you see the code:
, being a new design, has all-constexpr construction and destruction which avoids the need for static global variables, as has. Each of those static global variables requires an atomic fence just in case it has not been initialised, thus every retrieval of an error category bloats code and inhibits optimisation, plus makes the use of custom error code categories in header-only libraries unreliable. Boost.System has replicated the all-constexpr construction and destruction from ``, and thus now has similar characteristics in this regard.
Finally, this is a small but important difference. Under ``, this extremely common use case is ambiguous:
memcpy()’s the bits from source to destination, followed by memcpy() of the bits of a default constructed instance to source, and with a programmer-given guarantee that the destructor, when called on a default constructed instance, has no observable side effects. A surprising number of standard library types can meet this definition of move relocating, including std::vector<T>, std::shared_ptr<T>, and std::exception_ptr. [return]