On Fri, 27 Nov 2015 04:56:32 +0530, Gavin Lambert
I was referring to the hypothetical combiner function that accepted multiple fallible_result<>&& parameters (since it consumes all of them), and then returns its own fallible_result from one or more of them.
Within the function it will not be able to call any methods on the fallible_result<>&& parameters (since they're actually lvalues now), except for one very common case: auto a = std::move(paramA).as_result_or_error();
(And that this construct is not unreasonable as long as paramA is not accessed after this point -- it's no different from any other move.)
Since std::move is meant for, well, moving and not for accessing special functionality (at least in client code) I would consider this 'smelly'/unreasonable/'antipatternistic'...regardless of that, even if you do do this everything will still work (with the recently discussed changes) although with possibly slight codegen degeneration.
I was also referring to the compiler errors that would be generated from "improper use" being the same ones that people are likely to reflexively add std::move() calls to resolve.
Well that would mean that 'people' didn't 'RTM' i.e. they don't know what both fallible_result and std::move are for... You could just as well argue that you can circumvent RAII with placement new...the point is that you cannot unintentionally do the wrong thing...
The woe is that you'd also get a runtime assert since two fallible_results managed to exist at the same time again. But yes, that could only happen if you forgot to actually use them, or if you thought the errors meant that you were supposed to add std::move().
As above...
It does make the behaviour a little strange for the various cases though:
calcA(); // throws because fallible_result went uninspected calcB();
That's intended/by design behaviour, 'the classic EH style usage' (the
throw happens only if the call failed, i.e. the return value contains an
err_t, not T, so the err_t is thrown, with a possible transformation into
an object/wrapper more apt for EH but those are details I'd rather not go
at this stage)...what problem do you see here?
ps. if the functions in question would otherwise return void (and would
thus be transformed to return fallible_result
-------------- auto a = calcA(); auto b = calcB(); // asserts because two fallible_results exist // compiler error if a or b are used later without std::move
Again, intended behaviour - error on wrong usage (as there is no way for
the compiler and/or library to deduce whether you want the auto to mean T
or result_or_error
-------------- foo_error_t a = calcA(); foo_error_t b = calcB(); // no errors even if a or b go unused after this point // a & b are either valid or have error codes
Intended behaviour - error 'code' style - this is kind of like a
generalised concept of the std::pair
-------------- foo_t a = calcA(); // throws if calcA has an error foo_t b = calcB(); // throws if calcB has an error // a & b are both valid if you survive this far
Same/similar to your first example - intended behaviour - EH style...
-------------- auto a = calcA().as_result_or_error(); auto b = calcB().as_result_or_error(); // no errors even if a or b go unused after this point // a & b are either valid or have error codes
-------------- something(calcA(), calcB()); // asserts for two fallible_results
No longer, we fixed those, no? ;)
-------------- something(calcA().as_result_or_error(), calcB().as_result_or_error()); // might work or might assert depending on the compiler's mood
Same as above (fixed). (note: the as_result_or_error verbosity is only required if something() is a function template so implicit conversion does not kick in) -- "What Huxley teaches is that in the age of advanced technology, spiritual devastation is more likely to come from an enemy with a smiling face than from one whose countenance exudes suspicion and hate." Neil Postman --- Ova e-pošta je provjerena na viruse Avast protuvirusnim programom. https://www.avast.com/antivirus