Reputation: 16476
I have a function that will retry a function for a certain number of times and return whether it was successful:
template<typename Functor>
bool Attempt(Functor functor)
{
bool success = false;
size_t retries = MAX_RETRIES;
do
{
success = functor();
}
while (!success && retries-- > 0);
return success;
}
// usage:
bool success = Attempt([=]() {
return something_that_may_not_work_the_first_time();
});
This works fine and is used through out the code where I need to retry something a multiple number of times (serial comms for example).
However I have recently needed to Attempt
something that returns a std::optional<>
.
What I came up with is this:
template <typename T, typename Functor>
std::optional<T> Attempt(Functor functor)
{
std::optional<T> success{};
size_t Retries = MAX_VALIDATION_RETRIES;
do
{
success = functor();
}
while (!success && Retries-- > 0);
return success;
}
// usage
std::optional<unsigned int> response = Attempt<unsigned int>([=]() {
return something_that_returns_optional_unsigned_int();
});
Which works but is unsightly having the <unsigned int>
on both sides of the assignment operator.
Is there any template chicanery that can be added to deduce that?
Upvotes: 3
Views: 104
Reputation: 122460
All the types you specify explicitly can be deduced:
#include <optional>
template <typename Functor>
auto Attempt(Functor functor)
{
decltype(functor()) success{};
size_t Retries = 42;
do
{
success = functor();
}
while (!success && Retries-- > 0);
return success;
}
std::optional<unsigned int> something_that_returns_optional_unsigned_int() { return {};};
int main() {
auto response = Attempt([]{ return something_that_returns_optional_unsigned_int(); });
}
Upvotes: 4