Subject: Re: [boost] [review] Review of Outcome v2 (Fri-19-Jan to Sun-28-Jan, 2018)
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2018-01-29 00:53:28
> - "View this code in Github"
> This is fine for online viewing, but for a packaged release
> it's better to link the local source.
> - "contains an error information"
> "information" shouldn't have an indefinite article.
> - "It is worth turning on C++ 17 if you can, there are..."
> comma splice.
All fixed in develop branch.
> BUILD AND INSTALL:
> This section refers to all kinds of things that
> do not exist in the review version. Such as:
> - CMake
> - Single header version
> - outcome/include/outcome.hpp
The documentation is for the standalone edition. If the library is
accepted, it will be adjusted for the Boost edition.
> DECISION MATRIX:
> - The font size in the decision matrix scales with
> the page size, which may make it unreadable.
> (I had to zoom to 300%, before I could read the
> third flow chart) It's also completely unreadable
The decision matrix will likely be removed in the Boost edition, along
> RESULT<T, EC>:
> - OUTCOME_V2_NAMSPACE.
> This seems singularly pointless.
> How does accessing the namespace via a macro
> help with backwards compatiblity? It will
> break source compatibility exactly as much
> as if you just used a normal namespace. If
> you're concerned with binary compatibility,
> then the only thing that matters is the
> symbol mangling and there's no need to
> expose this ugliness to the user.
> Also, why is this attached to result, and
> not in its own section.
The reason is that Outcome is expected to be used extensively in ABI
boundaries. So if DLL A has public APIs returning Outcome, and DLL B has
public APIs returning Outcome, but DLL A uses a different version of
Outcome to DLL B, we specifically want to force the compiler to utilise
the ValueOrError concept interoperation mechanism rather than having
incompatible Outcome implementations corrupt one another.
> - If some type `X` is both convertible to `T` and `EC`
> parallel structure: 'convertible' should either be
> placed before 'both' or be duplicated on both
> sides of the 'and.'
> - You say that it's ambiguous if the constructor
> argument is convertible to both T and EC. Is
> it still ambiguous if it is exactly T or EC?
> If so, that seems wrong. If not, you need to
> explain the behavior more clearly.
All implicit conversions disable if there is any relationship between T
and EC whatsoever. Yes, that's far too harsh. But that was what the
first review concluded was safe, and there was universal consensus on
that decision (eventually, it took a very long discussion).
I have fixed the tutorial wording to make this clear.
> - Why do you need to use tagged constructors
> instead of just casting? (I suppose the fact
> that you felt the need to have these indicates
> to me that an exact match /is/ ambiguous.)
The previous review wanted to avoid the surprises that one can
experience with constructing std::variant, hence the much stricter
> - "Suppose we will be writing function..."
> function needs an article.
> - "integral number"
> This is just a verbose way of saying "integer."
> - "Type result<void>"
> -> "The type result<void>"
> - "Class template `result<>` is declared with attribute [[nodiscard]]
> which means compiler"
> Add "the" before "class," "attribute," and "compiler."
> - "In the implementation we will use function `convert`"
> "*the* function"
> - "#2. Function `.value()` extracts the successfully returned `BigInt`."
> "*The* function". Also it's an int, not a BigInt.
All fixed in develop.
> - I noticed that the starts of the list items after the
> #N. are not vertically aligned, which looks a little odd
> for #1, #2, #3, and #4, which are short enough to make it
> obvious. This appears to be because each item is
> treated as a normal paragragh which happens to begin
> with a number instead of a proper list item.
I'm personally fine with it.
> - "It implies that the function call in the second argument"
> I presume that it takes a generic expression, not just
> a function call.
> - "It is defined as"
> The antecedent of "It" is ambiguous. It refers to
> the function in the preceding sentence, but when
> I first read it I assumed that it referred to "OUTCOME_TRY"
Fixed in develop.
> - I think the name OUTCOME_TRY is misleading because it has
> the exact opposite meaning of "try." try/catch stops
> stack unwinding, but OUTCOME_TRY is used to implement
> manual stack unwinding.
I think the ship has sailed on that. Swift, Rust etc all use try. The
proposal before WG21 is try. I think it better we conform to what other
languages are doing unless there is a good reason not to.
> - I'm not sure what I think of as_failure. I'd actually
> prefer to just write return r;
I think you mean `return r.error();` as the T types are not compatible.
> - "this will be covered later"
> A link would be nice.
Improved in develop branch.
> - I can't see the point of having success<void>
> default construct T. It seems like dangerous
> implicit behavior, unless you make it so that
> success is variadic and constructs the result
> in place.
Can you explain why it would be dangerous?
> Also, there is no type named success.
> It's called success_type.
Good point. The reason is that on C++ 17, we were using a success<T>
type directly constructible via template deduction guides. But the C++
17 standard is subtly broken here, I believe it gets fixed in C++ 20. So
I killed off the C++ 17 implementation, we now use the C++ 14
I've logged the issue to https://github.com/ned14/outcome/issues/123
> - OUTCOME_TRYV
> I think it would be nicer if you used a single
> macro that has different behavior depending
> on whether it is passed 1 or 2 arguments.
It'll need some preprocessor metaprogramming, but sure. Logged to
> would be even better if you could also merge
> OUTCOME_TRYX in. The behavior of OUTCOME_TRYV
> is logically the same as that of OUTCOME_TRYX for
> a result<void>.
Alas expression TRY is not portable across compilers, so I'll be keeping
that as its own macro to prevent portability problems.
> - "outcome<> has also function"
> -> "outcome<> also has a function"
Fixed in develop.
> - How does outcome::value interact with custom
> error_code type? It needs to know what exception
> type to throw, no?
Covered in https://ned14.github.io/outcome/tutorial/default-actions/
> - "...symbolising that into human readable text at the
> moment of conversion into human readable text"
> This sentence does not parse.
> - "#4 Upon a namespace-localised `result` from library
> A being copy/moved into a namespace-localised
> `result` from C bindings..."
> I can't understand this at all. What is a
> "namespace-localised result" How does this
> relate to a custom payload? A plain error_code
> has everything you need to set errno.
Namespace localised results are covered slightly later in the same
section starting from
Basically we define a local EC type to cause ADL for the extension
points into our local namespace, and then locally bind `result` into our
Most codebases using Outcome which are of any size will namespace
localise their result implementation in this fashion.
> - In code examples, _'s can sometimes disappear
> mysteriously. I haven't figured out the exact
> conditions, but resizing the window changes the
> result. Seems to be a result of overlapping with
> the line underneath.
Ah, great spot. I had been stumped. Lines overlapping is a very likely
cause of that problem. Logged to https://github.com/ned14/outcome/issues/125
> - Also, the lines are too long. They still wrap
> even when I put the browser in full screen.
> (Admittedly, the VM is only 1280x768)
Logged to https://github.com/ned14/outcome/issues/126
Thanks for the feedback!
-- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk