2017-01-17 18:57 GMT+01:00 Niall Douglas
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
> wrapped up with convenience macros and other ease of use bits. That's all. 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
file(path_type _path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept; No surprises there.
For operators and conversion, the chances are if those are important for your code base in an extern pan-TU space, then the sea of noexcept design pattern is a bad fit for your code base. Sea of noexcept suits code whose classes abstract out operating system specific implementation e.g. a windowing framework. It definitely would not and does not suit code which say parses text and where parsed things need to be compared and converted.
I'm really not claiming sea of noexcept suits most code, rather it suits some types of code, particularly very large code bases where you need an insane focus on worst case performance i.e. you can't allow C++ to call malloc for you. Let me put this another way: if your classes are easily wrapped into Microsoft COM objects because they use so few modern C++ features like allocating memory :), sea of noexcept is definitely for you. If the limitations of a COM object would make your classes infeasible, sea of noexcept is a bad fit for your code.
(For reference, a COM object is basically a C++ class with only virtual functions returning a HRESULT and only accepting integral types or other COM objects. You initialise one with a static Init() function, and they are always reference counted as if by shared_ptr. Very straightforward and very easily implemented in C too)
Does that make more sense?
Let's see. So now, I my understanding is the following. If a programmer decides that certain section of the program (the see of noexcept) requires explicit control flow when it comes to handling "disappointments", Boost.Outcome is just the tool he needs because it offers a set of convenient types, tailored for optimum performance + convinience operators + a dedicated control flow statement hidden under macro BOOST_OUTCOME_TRY. did I get it right? Regards, &rzej;