On 26/05/2017 17:33, Vicente J. Botet Escriba wrote:
std::experimentall:expected
::error, doesn't throws. I don't see a use case where we want to retrieve an error without checking before. Maybe you have a case.
Perhaps unit tests, where you're expecting an error but the code unexpectedly succeeds. Also as in the case above, when you forget that an empty state exists: result<T> r = something(); if (r.has_value()) { do_something(r.value()); } else { log(r.error()); // oops, r might be empty } I dislike gratuitous UB, and Niall assures us that optimisers will discard a double check so it should be reasonably cheap.
Le 26/05/2017 à 01:36, Gavin Lambert a écrit :
I don't like the idea of a default-constructed T because T is not always default-constructible, and this makes it inconsistently behaved for different T and makes it harder to use uniformly in containers, especially in generic code.
For the record, not having a default constructor at all also makes it harder to use in containers, so I don't like that either. Though it's a weaker dislike than my dislike of a default-constructed T or E.
I don't like the idea of a default-constructed E because by convention (even if not quite in fact as Niall has pointed out -- though I've yet to see a platform where a 0 error code *didn't* mean success, other than cases where the formal type is int but is actually used as bool) the default-constructed error_code means "no error", and this is heavily reinforced by its operator bool semantics.
I do like the idea of a non-default-constructed error code, because failure to initialise the result does seem like an error to me. Niall points out that this is harder to detect and treat specially in code but I don't agree with that; as long as a suitably unique error code is used then a simple assert in the error path would pick it up, no problem.
If the consensus is that an initial non-default error code is not satisfactory, then a formal empty state seems to me like the least worst alternative. I just know that it's going to bite someone at some point.
If we don't provide a default constructor for expected<T> we could be forced to use optional
. This allows to don't pay for this empty state when we don't need it. The problem is that we are paying more than needed when we need it.
We have two options: * we specialize optional
> * we rename the intended specialization xxx<T> is similar to optional . xxx could be outcome::result or optional_expected
I'm not entirely sure how this relates to what I was saying.
At least in terms of storage, the current implementation of empty state
is presumably free (it should be no more expensive to internally store a
variant