let's take this short example:
std::expected<std::any, Fault> doN(int n)
{
switch (n)
{
case 1: return do1();
case 2: return do2();
// ...
}
}
std::expected<int, Fault> do1()
{
if (error)
{
return std::unexpected<Fault>({/* ... */});
}
return 23;
}
If I do it this way and call auto result = doN(1)
without errors, then result.value()
type is std::expected<int, Fault>
and not int
(without mentioning the any_cast
).
The way I found to solve this is to destruct the result of the inner call:
std::expected<std::any, Fault> doN(int n)
{
switch (n)
{
case 1:
auto value = do1();
if (value.has_value()) {
return value.value();
}
return std::unexpected(value.error());
// ...
}
}
The type doN(1).value()
is int
.
So my question is: How can I simplify that? Is there a way to return the function call result?
How can I simplify that? Is there a way to return the function call result?
In order to simplify your approach, you could use std::expected::transform
. Something like:
return do1().transform([](int value) { return std::any(value); });
The transform method does the following:
std::expected
contains a value (do1().has_value()
)std::any(value)
) and returns a new std::expected
with the transformed valueThat means, might be able to write:
// Helper function to convert any std::expected<T, Fault> to std::expected<std::any, Fault>
template<typename T>
std::expected<std::any, Fault> to_any(std::expected<T, Fault> exp)
{
return exp.transform([](auto value) { return std::any(value); });
}
// Function that calls the appropriate function based on input
std::expected<std::any, Fault> doN(int n)
{
switch (n) {
case 1: return to_any(do1());
case 2: return to_any(do2());
// ...
default: return std::unexpected<Fault>({/* some error */});
}
}