If I am writing a function that returns an std::expected
object and potentially calls other functions that return std::expected
objects, I find myself writing code snippets like this very common.
struct Foo { };
std::expected<Foo, std::string> f();
auto res = f();
if(!res) return std::unexpected { res.error() };
auto val = res.value();
// do something with val
So I write a macro like this that "returns" the value in case of success and the error in case of failure.
#define CHECK(expr)\
({\
auto res = expr;\
if(!res) return std::unexpected { res.error() };\
res.value();\
})
I can then use it in this way:
Foo foo = CHECK(f());
I assume the lifetime of the variables in the inner scope should be as long as the assignment expression. Is this correct? Is there any situation where this could go wrong?
With this macro, you'd write functions like so:
I'd argue that avoidance of this pattern is what the monadic method
std::expected<T,E>::and_then
was intended for:And in this particular case, it could be shortened even further:
though realistically, I'd imagine writing out the lambdas would be the more common case in actual code.
Compiler Explorer: https://godbolt.org/z/vovTYfxf4