Thanks for a detailed reply. This is what I understood so far. One of the main goals of Boost.Outcome (apparently not the only one) is to make it easy for you to go from an island of exceptions into the sea of noexcept (and probably the other way around also).
Correct. Outcome basically provides a less clunky to use and hard coded
std::expected
The reason you would encourage the explicit control path over the implicit one (where exceptions are thrown around) is for the correctness of the program -- not necessarily performance.
Did I summarize it correctly?
Not quite. "is for the correctness of the program" => "is to make the programmer explicitly state in code the correctness of the program" For some code bases e.g. a filing system it is really important the programmer explicitly writes out what will happen when something goes wrong. For example, originally NTFS was written using SEH and that turned into a maintenance nightmare. So (I'm told) they gutted the SEH implementation and put back C error codes because they force people changing the code to think deep and hard about handling errors at the point of changing the code. I've no idea if that's true or not, but a NT kernel programmer working at Microsoft told me that at a conference once. It sounds plausible.
If yes, there comes another question. One of the main reasons exceptions were introduced in the first place was to be able to report failures from functions that cannot use the return value for this purpose: constructors, conversion operators, and other operators. How do you deal with these functions in the sea of noexcept?
I assume you really mean here "what about classes in extern space?".
Outcome has no role in those. You'll need to make your constructors all
thin forward only affairs, noexcept and private, and provide a static
init function to construct them which does all the real work. Same as
since forever in C++. For example in AFIO v2 to open a file returning an
afio::file_handle:
static result