On 19/11/2015 12:43, Vicente J. Botet Escriba wrote:
Imagine a function that calculates several results, some of which may fail, and then calls a combiner method to choose the "best" non-failing result of the set. Wouldn't the combiner naturally expect a fallible_result<T>&& as its inputs, since it wants to consume them?
I suppose you could force it to accept result_or_error<T> instead, but since this isn't the return type of the function it inhibits using generic type-deducing template code with simplified expressions like: return combiner(calcA(), calcB(), calcC());
The more problematic case is if the combiner was not expecting failure, and so someone used the same expression with a combiner that accepted T. So the compiler calls all three calc methods (constructing fallible_result<T>s along the way), then gets around to converting the first one back to T, which throws. This is ok, but then the other two are destroyed; and if at least one of these throws too, then you're dead.
Sure, you can tell people to only use this as a standalone expression and not as a function parameter, but this seems very fragile. People like to inline things, especially rvalues.
Your example can be adapted to several variables of type faillible_result<T>
auto a = calcA(); auto b = calcB(); auto c = calcC();
if (a.value()) // can throw :(
I like the intent of faillible_result<T>, but as you described it could be more dangerous than safe.
That's sort of what I meant in my original post about requiring an explicitly different type for variable declarations instead of using auto. Although correct me if I'm wrong, but given: fallible_result<T>&& calcA(); auto a = calcA(); Isn't the type of "a" fallible_result<T> rather than fallible_result<T>&&? Theoretically the author made it unusable in this case since the methods only work on rvalue references (although BTW the syntax to do this is illegal in VS2013, which is what I have handy ATM, so I couldn't verify that this actually generates an error). It also asserts if more than one fallible_result exists on the thread, which would catch the case that I mentioned too. Though asserts only help you in debug builds, of course. (This probably also means that it's a bad idea to have a coroutine suspension point between calling such a function and resolving the fallible_result...)