IIUC, what you want is to have outcomes that copy/move well each one on each other. That was exactly a motivating reason for choosing this design originally. Having the same base storage implementation should allow the compiler to completely eliminate memory copying to implement layout changes when a personality is changed. How outcome ovoids this copying? Compilers spotted the common outcome::value_storage during moves when it was identical, and totally eliminated any memory copies. Okay, so the single thing outcome::outcome provides is the conversion from the other Outcomes. I believe this is great and I will add it to the open question for std::expected as I've already notified privately to you (waiting a response :) ) Is this the major drawback you find to the use of std::expected and std::optional? No, not at all. Very recent optimisers e.g. in better than clang 4.0 and in GCC 6.0 with -O3 optimisation turn out to have rendered the common storage design choice no longer appropriate. But that wasn't the case when I began Outcome two years ago. And then? clang 4.0+ and GCC 6.0+ with -O3 optimisation appear to now be clever enough to spot trivial move constructors and trivial types, and not copy memory when the bits in memory would not change. Do you mean that now we can use optional and expected without any
Le 24/05/2017 à 17:20, Niall Douglas via Boost a écrit : performance penalty and that the design of Outcome is not needed any more?
I would therefore expect that your reference Expected implementation would now be identical or very similar in runtime performance to Outcome on clang 4.0+ and GCC 6.0+. MSVC does, of course, still have some way to go yet, but VS2017 is a world of improvement over VS2015.
I was looking for any advantage of the design of Outcome ;-)
You would thus exchange (slightly) worse performance of successful code in exchange for vastly better and predictable performance of unsuccessful code.
Note that the cost of throwing and catching a C++ exception with a table based EH C++ compiler is highly unpredictable, and costs between 1500-3000 CPU cycles per stack frame unwound between the try and catch site. You can find the benchmark in the benchmark directory in Outcome's git repo. So you are comparing to the use of exceptions here and not to the use of output error codes? I am comparing the cost of throwing and catching exceptions to returning an expected with unexpected state.
Throwing an exception should be rare, exceptional, and most of the cases
we could ignore them.
expected is there to return expected values and possible errors, but
these error are not necessarily exceptional and that could occur more often.
I will never change a function that return TR and that can throw
bad_alloc for a function that return expected
What is the behavior on the absence of exception on the functions that throw exceptions? Are these functions disabled? Does the fucntion terminate? Calls a handler? All exceptions Outcome ever throws are done via a user redefinable macro. Those macros are listed at https://ned14.github.io/boost.outcome/md_doc_md_04-tutorial_c.html.
If C++ exceptions are enabled, the default macro definition throws the exception.
If C++ exceptions are disabled, the default macro definition prints a descriptive message and a stacktrace to stderr and calls std::terminate(). This is similar to what BOOST_THROW_EXCEPTION does, isn't it? Why re-invent the wheel? End users can define the Outcome exception throwing macros to call BOOST_THROW_EXCEPTION if they wish. For standalone Outcome users, the default behaviour is minimal, but sufficient.
Boost users should have already a default for BOOST_THROW_EXCEPTION and shouldn't need to add any additional customization for what to do when exceptions are not enabled. I don't agreed with the change on BOOST_THROW_EXCEPTION done by Emil, but the reality is that it is there now. Users of Boost should not customize each library, when there is already a common mechanism.
is an excellent neighbour to all other C++ libraries as for example? It pollutes no namespaces, interferes in no way with other C++ including other versions of itself. You can mix multiple versions of Outcome in the same binary safely. There are several version of Outcome? Currently every time I commit to the git repo there is a new version of Outcome. The ABI is permuted with the SHA of the git. This prevents unstable versions of Outcome conflicting with different unstable versions of Outcome in the same process.
Hugh. I don't see how would someone like to use two unstable version of the same library.
I will, at some future point, declare a stable ABI and pin it forever to v1 of the ABI and have that checked per commit by Travis.
I don't see any added value to this versioning. Up to you.
AND build systems, I'm less concerned by the build systems, but could you elaborate? Outcome doesn't require any magic macros predefined and can be used by end users simply by dropping a tarball of the library into their source code and getting to work. While this could be a quality for a standalone library, this is not a quality for a Boost library. The other C++ 14 library in Boost does not require any of Boost either.
Oh, yeah I forgotten, Boost.Outcome is a C++14 library and so it cannot use Boost and reinvent the wheel ;-)
(And my thanks to Andrzej for the motivating example on the landing page of the docs, he did a great job capturing the universal error handling framework aspect of Outcome. I would love to know if reviewers can make sense of it, or did it just confuse the hell out of everybody)
Could you tell us which example? It's the landing page motivating code example. Bottom of https://ned14.github.io/boost.outcome/index.html.
No this example doesn't show any advantage of Boost.Outcome, quite the opposite. However the other example that Andrzej has posted recently is a better example as I have already said as a response. The only difference was returning result instead of outcome, and removing the exception throwing function call. Otherwise the examples are identical.
The return value is very important; the example show an important thing of Boost.Outcome: error propagation. Vicente