I've seen early proposals of this and never been a big fan of the syntax, I'm disappointed it made it in to C++23. Monads can be useful if they enable composition across different concepts, but this is syntactic sugar that IMO can be expressed in a nicer way with an immediately evaluated lambda and early returns.
Compare
const auto ageNext = fetchFromCache(userId)
.or_else([&]() { return fetchFromServer(userId); })
.and_then(extractAge)
.transform([](int age) { return age + 1; });
with
const auto ageNext = [&]() -> std::optional<int> {
auto user = fetchFromCache(userId);
if (!user) { user = fetchFromServer(userId); };
if (!user) return std::nullopt;
return extractAge(user) + 1;
}();
If you allow GCC/Clang extensions, the first two lines in the lambda can be even turned into
auto user = fetchFromCache(userId) ?: fetchFromServer(userId);
Compare
with If you allow GCC/Clang extensions, the first two lines in the lambda can be even turned into