- error_type& .error_raw() - reinterpret_cast
evidently we don't like the _raw suffix.
.error_unsafe(), .unsafe_error(), .unchecked_error() all work for me too. For me operator*() and operator->() absolutely needs wide contracts. If people want the performance of narrow, they can manually write out excpt.value_raw()->var rather than excpt->var, or subclass expected with a narrow reimplementation of operator*(). It won't kill them.
Outcome distinctly categorises failure-due-to-error and failure-due-to-exception. I think that important given its different use case to Expected which is explicitly for low latency and C++ disabled environments. Do you mean exceptions disabled? How would you have exceptions when the exceptions are disabled?
But Expected as the STL type, I think your proposal is safe. Most of your users will throw exceptions for exceptional situations.
I guess that when exceptions are disabled, an implementation will just terminate the program, isn't it?.
Not at all. Indeed MSVC can still throw and catch exceptions with exceptions completely disabled so long as the throw is caught before leaving the stack frame in which the throw is done. For all major compilers, you can compile some files with C++ exceptions enabled, others not. exception_ptr is safe to transport thrown and caught C++ exceptions through exceptions disabled code. You can thus "bundle up" usage of the STL into islands kept separate from the rest of your code, and pass thrown and caught exceptions between islands of exceptions enabled C++ using Outcome.
I can not ignore this Outcome review, but I have not see too much people saying that the semantic you have done to this functions is the good one.
Strange. I've been surprised at how little criticism there has been of my design choices. Silence can be interpreted both ways I guess.
Nevertheless I will add an open point about having narrow and wide contract for the error access. I will add also another open point to have the possibility to return E{} when the contract is wide instead of throwing an exception.
IMHO we need just the narrow contract function. The other can be built on top of this by the user or by Outcome.
Remember Expected proposal has already two open_points for err error_or(exp, err) and bool has_error(exp, err)
I do agree with this philosophy, but if you're going to go narrow, you need to go narrow on everything including .value(). You need to consistently choose one or the other. No middle ground. An advantage of all narrow is you can eliminate bad_expected_access and simplify the Expected proposal to be merely a thin API convenience layer wrapping std::variant. A separate std::result, as Peter suggested, can layer on top of std::expected with all wide observers as would make much more sense for an object returning uncertainty. But it's up to you.
What your checked_outcome<T>::error will return if the is a exception_ptr? Ah, finally someone brought this up. Good!
It returns an error_code with bad_outcome_category and bad_outcome_errc::exception_present.
Ugh. Why your design is never coherent. Why you don't name your functions after what they do?
I would call my design asymmetrical. I can see why some would call it incoherent.
What if the exception_ptr contains an arbitrary exception? No way to obtain an error_code :(
There is a macro to do that in the presented library. Peter has discovered it to be over engineered given current compilers, and so https://github.com/ned14/boost.outcome/issues/50 will replace it.
I believe your design is too much guided by your AFIO use case. Not all the applications use system errors.
As the documentation tries to show, Outcome only makes sense for those
users of expected