Tangentially related, but if you don't have access to c++23 or you don't like monadic properties, passing by reference and returning bool success can emulate or_else, transform, and_then with || &&
bool fetchFromCache(int userId, UserProfile& profile);
bool fetchFromServer(int userId, UserProfile& profile);
UserProfile profile;
if (!fetchFromCache(userId, profile) && !fetchFromServer(userId, profile)) {
std::cout << "Failed to fetch user profile.\n";
return;
}
or just to prove a point, although even more unreadable than the monads:
bool extractAge(const UserProfile& profile, int& age);
UserProfile profile;
int age;
if (
(!fetchFromCache(userId, profile) && !fetchFromServer(userId, profile))
|| !extractAge(profile, age)
) {
std::cout << "Failed to determine user's age.\n";
return;
}
int ageNext = age + 1;
This probably isn't a great example usecase for this, but its helpful when creating composable transform pipelines
user_id = 12345
user = fetch_from_cache(user_id) or fetch_from_server(user_id)
age_next = user and (user.age + 1)
if age_next:
print(f"Next year, {age_next} years old")
else
exit("Failed to determine next age")