+++
title = "History"
weight = 90
+++

Outcome has had an interesting history, and it is worth summarising it here to show how a
Boost library comes to life. The following recollections are by Niall Douglas, and may be
faulty due to his aging memory.

{{<if_boost "/history/graph.png">}}
{{<mermaid>}}
gantt
  dateFormat YYYY-MM
  title History of the Outcome library
  Outcome v1: done, des1, 2014-06,2017-05
  Boost peer review of v1: done, des2, after des1, 30d
  Outcome v2 (complete redesign based on first review feedback): done, des3, after des2, 2018-01
  Boost peer review of v2: done, des4, after des3, 30d
  Outcome v2.1 (changes from second review): active, des5, 2018-03, 2021-04 
  Outcome v2.2 (changes from user feedback on v2.1): des6, after des5, 2023-04 
  section Events
  Separated from AFIO v1: crit, done, 2014-06,4d
  Boost.Expected added: crit, done, 2014-10,4d
  Boost.Expected replaced with feature complete basic_monad: crit, done, 2015-08,4d
  Non-allocating future-promise implementation dropped: crit, done, 2016-05,4d
  C++ 11 support dropped: crit, done, 2016-06,4d
  Implemented LEWG expected&lt;T, E&gt; using basic_monad: crit, done, 2017-02,4d
  Outcome v1 replaced with prototype v2 in git repo: crit, done, 2017-07,4d
  Boost.Outcome generated by script from Outcome repo: crit, done, 2017-10,4d
  New tutorial finally complete: crit, done, 2017-12,4d
  Outcome v2.1 feature complete, maturation begins: crit, done, 2018-04,4d
  Boost.Outcome docs gain BoostDoc theming: crit, done, 2018-12,4d
  Release of v2.1 into Boost 1.70: crit, active, 2019-04,4d
  Release of v2.2 into Boost 1.76: crit, active, 2021-04,4d
  Outcome goes ABI stable: crit, active, 2022-04,4d
{{</mermaid>}}
{{</if_boost>}}

## The genesis of Outcome v1 (2014 - 2017)

The git repo began life as a "Boost.Spinlock" in June 2014 hived out of Boost.AFIO v1 where it had existed
for some time as an internal library. In October 2014 I added in the original prototype
Boost.Expected reference library as a git submodule, and began developing a non-allocating
`future<T>`/`promise<T>` as an extension of `expected<T, std::exception_ptr>` as a faster,
monadic future-promise was something which AFIO v1 sorely needed.

The original prototype Boost.Expected library was a large and very complex beastie.
I was fortunate to be employed on a contract in late 2014 early 2015 where I saw it deployed at
scale into an existing large C++ codebase. Expected was really great and powerful, but it absolutely
murdered compile times in a large C++ codebase, and made LTO effectively infeasible.
I also found its implementation non-conducive to implementing
future-promise with it, and so I resolved to implement a much more powerful policy driven
monad factory which could stamp out everything from an `option<T>` right through to a
future-promise pair, all using the exact same `basic_monad<>` and therefore all with a full
monadic programming API, C++ 17 continuations/monadic bind and intelligently convertible into one another.
Moreover, all this needed to have an absolute minimum impact on compile times and runtime
overheads, neither of which were strengths of the original prototype Boost.Expected library.

By August 2015 "Boost.Monad" was delivering on all those requirements and then some, but it lacked
maturity through use in other code. Summer 2015 saw the Boost peer review of AFIO v1 which
was roundly rejected. After considering the ample review feedback, it was realised that
[AFIO v2](https://ned14.github.io/llfio/) would be a very different design, one no longer using futures, memory allocation
nor C++ exceptions. As AFIO v2 was started from scratch and using Outcome heavily from the
very beginning (every AFIO v2 API returns a `result<T>`), Outcome began to gain bug fixes and
shed features, with the non-allocating future-promise implementation being dropped in May
2016 and a large chunk of type based metaprogramming being replaced with cleaner variable template metaprogramming
in June. After CppCon 2016 in September, then began the long process of getting Outcome
ready for Boost peer review in Q1 2017 which involved a repeated sequence of complete rewrites
of the tutorial in response to multiple rounds of feedback from the C++ community, with
at least four complete rewrites currently at the time of writing.

In parallel to all this development on Outcome, Expected went before the LEWG and entered
the C++ standards track. As the WG21 meetings went by, Expected experienced a period
of being stripped back and much of the complexity which had so murdered compile and
link times in 2014-2015 fell away, thus the Expected proposed in P0323R1 ended up landing
so close to Outcome that in January 2017 it was just a few hours work to implement
Expected using the core `basic_monad` infrastructure in Outcome. That highly flexible
policy based design which made monadic future-promise possible made it similarly easy
to implement a highly conforming Expected, indeed in early 2017 Outcome's Expected was much
closer to [P0323R1](http://wg21.link/P0323) than any other implementation including the LEWG reference implementation.
And unlike the LEWG reference implementation, Outcome has had eighteen months of that
finely tuned patina you only get when a library is in use by other code bases.

In February 2017 it became realised that the userbase really wanted a high quality `expected<T, E>`
implementation rather than anything similar but not the same which Outcome had invented.
The only just implemented Expected implementation based on `basic_monad` therefore took
primacy. The final rewrite of the documentation before peer review submission was one
which made it look like Outcome was primarily an `expected<T, E>` implementation with a
few useful extensions like `outcome<T>` and `result<T>`. I was sad to so pivot, but it
was obvious that Outcome would see far wider popularity and usage as primarily an Expected
implementation.

Almost three years after its beginning, Outcome v1 finally went before Boost peer review
in May 2017 which turned into one of the longest and most detailed peer reviews Boost has
done in recent years, with over 800 pieces of review feedback submitted. It was by consensus
rejected, [with substantial feedback on what to do instead](https://lists.boost.org/boost-announce/2017/06/0510.php).

## Outcome v2 (2018)

During the very lengthy peer review, roughly three groups of opinion emerged as to what
a `value|error` transporting class ought to look like:

<dl>
<dt><b>1. Lightweight</b></dt>
<dd>A simple-as-possible <code>T</code> and/or <code>E</code> transport without any
implementation complexity.</dd>
<dt><b>2. Medium</b></dt>
<dd>A variant stored <code>T</code> or <code>E1</code> ... <code>E<i>n</i></code>
where <code>T</code> is the expected value and <code>E1 ...</code>
are the potential unexpected values. This implemention really ought to be implemented
using C++ 17's <code>std::variant<...></code> except with stronger never-empty guarantees.
</dd>
<dt><b>3. Heavy</b></dt>
<dd>A full fat Either monad participating fully in a wider monadic programming framework for C++.</dd>
</dl>

Peter Dimov was very quickly able to implement an `expected<T, E1, ...>` using his
[variant2](https://github.com/pdimov/variant2) library, and thus there seemed little
point in replicating his work in an Outcome v2. The lightweight choice seemed to be the
best path forwards, so in June 2017 the bare minimum `result<T, E>` and `outcome<T, EC, P>`
as presented in this library was built, using the same constructor design as `std::variant<...>`.
Significant backwards compatibility with v1 Outcome code was retained, as the review
had felt the basic proposed design fine.

A period of maturation then followed by porting a large existing codebase using Outcome v1
to v2, and writing a significant amount of new code using v2 to test it for unanticipated
surprises and bugs. Quite a few corner cases were found and fixed. At the end of September
2017, Outcome v2 was deemed to be "mature", and a script generated "Boost edition" made
available.

All that remained before it was ready for a second Boost peer review was the
documentation. This took four months to write (same time as to write the library itself!),
and in January 2018 Outcome had its second Boost peer review, which it passed!

## Outcome v2.1 (2019 - 2020)

The changes requsted during the review of v2.0 were fairly modest: `result` and `outcome` would
be renamed to `basic_result` and `basic_outcome`, and a clean separation of concerns between the
`basic_*` layer and the "convenience" layer would be created. That suited Outcome nicely,
as the `basic_*` layer could have minimum possible header dependencies and thus minimum possible build times
impact, which was great for big iron users with multi-million line C++ codebases. This also
had the nice side effect of permitting both Boost and `std` implementations to be supported
concurrently in both Outcome and Boost.Outcome. 

By April 2018, v2.1 was feature complete and entered a six month period of maturation and
battle hardening under its already extensive userbase. However Outcome passing its review in January 2018 had much more consequence than I could have ever
expected. Unbeknownst to me, some of the WG21 leadership had interpreted the success of
Outcome, and especially its divergences from WG21 Expected into a more complete substitute
for C++ exception handling, as a sign that the C++
exception handling mechanism was no longer fit for purpose. [It was thus proposed
to remedy the standard exception handling mechanism into something much more
efficient, thus rendering Outcome obsolete in future C++ standards (P0709 *Zero overhead exceptions*)](http://wg21.link/P0709).

Concurrently to that, just before the review of Outcome 2.0, I had mooted a number of semantic and compile time performance
improvements to `<system_error>` with the proposal that we mildly break Boost.System with
improvements and see how badly real world code broke in response. This was not widely
accepted at that time (though they have been since incorporated into Boost.System, and proposed
defect remedies for `<system_error>` for C++ 23). I therefore wrote [an improved `<system_error2>`](https://ned14.github.io/status-code/) which fixed all the problems
listed at [P0824 (Summary of SG14 discussion on `<system_error>`)](https://wg21.link/P0824)
and fixed up Outcome so one could use it without any system error implementation,
or with the STL one or with the proposed improved one. This improved `<system_error2>`
was then proposed as [the standard library support for Zero overhead exceptions as proposed
`std::error`](http://wg21.link/P1028).

A flurry of papers and discussion then resulted, running up to the Prague 2020 WG21
meeting where WG21 liked the library part of deterministic exceptions i.e. `std::error`,
and wanted to see a working implementation of a compiler implementing the language
part before moving further. The covid pandemic then ceased face to face meetings which
deeply impacted WG21 productivity, so everything large which was not yet approved for
entry into C++ 23 went on pause.

## Outcome v2.2 (2021)

Outcome was sufficiently popular, and widely known as the closest simulacrum of deterministic
exceptions currently available in C++, that it was regularly benchmarked as such on an 'as if'
basis by a number of people in the wider C++ ecosystem, including comparing their 'better Outcome
alternatives' to Outcome, where invariably Outcome appeared to lose badly in various
synthetic tests. Whilst any empirical measurements in the real world code never showed
a statistically significant difference, it was certainly true that v2.1's codegen in
assembler was not ideal.

On the behalf of WG21, Ben Craig did some benchmarking work on Outcome v2.1 in [P1886 *Error speed benchmarking*](https://wg21.link/P1886),
where it did not perform as well as expected compared to alternatives such as returning
a simple integer from a function. This led to a
[`better_optimisation`](https://github.com/ned14/outcome/tree/better_optimisation) branch.
The changes were felt worth merging into Outcome as v2.2.0, the first major version release
since Outcome entered Boost in early 2019. To give enough time to sign post to users that these
source incompatible changes were coming, all of 2020 was given over to announcement of the
upcoming merge of the breaking v2.2 branch into master branch in early 2021.

In terms of codegen benefits for proposed `std::error` based code (i.e. code using
[Outcome experimental]({{< relref "/experimental" >}})), v2.2 implements a library-based
emulation of [P1029 *move = bitcopies*](https://wg21.link/P1029), a proposed compiler
enhancement which can treat some move-only types as bags of bits. This very significantly
improves the appearance in assembler of experimental Outcome based code.

## Outcome v2.2.3 (2022)

Outcome v2.2 saw much popularity and very few issues reported after a year in the wild,
so the decision was taken [to write the v2.2.3 Outcome ABI into stone]({{% relref "/abi-stability" %}}) going forward.
This is the guarantee that binaries compiled with the v2.2.3 release will link and work
without issue with binaries compiled with any later version of Outcome.

This pretty much draws a line under further significant development of Outcome -- it
has now effectively entered 'sustaining', as big multinationals would term it i.e.
only small bug fixes and maintenance for future toolchains and languages etc would
be expected going forth from now.
