Monadic operations with std::optional
Can you explain and provide examples of the monadic operations available for std::optional in C++23?
In C++23, std::optional introduces support for monadic operations. These operations allow you to work with optional values in a more functional way, enabling you to chain operations together and handle empty optionals gracefully. The main monadic operations are and_then, or_else, and transform.
and_then()
This operation allows you to chain optional-producing operations. If the optional has a value, and_then applies the given function to the value, which should return another optional. If the original optional is empty, and_then returns an empty optional.
#include <iostream>
#include <optional>
std::optional<int> square(int x) {
return x * x;
}
int main() {
std::optional<int> maybe_int = 10;
auto result = maybe_int.and_then(square);
if (result) {
std::cout << "Result: " << *result << '\n';
}
maybe_int = std::nullopt;
result = maybe_int.and_then(square);
if (!result) {
std::cout << "Result is empty" << '\n';
}
}This will output:
Result: 100
Result is emptyor_else()
This operation allows you to provide an alternative optional value if the original optional is empty. If the original optional has a value, or_else returns it. If the original optional is empty, or_else returns the result of the given function, which should return another optional.
#include <iostream>
#include <optional>
std::optional<int> get_default() { return 42; }
int main() {
std::optional<int> maybe_int = 10;
auto result = maybe_int.or_else(get_default);
std::cout << "Result: " << *result << '\n';
maybe_int = std::nullopt;
result = maybe_int.or_else(get_default);
std::cout << "Result: " << *result << '\n';
}This will output:
Result: 10
Result: 42transform()
This operation allows you to apply a function to the value in an optional, if it exists. If the optional is empty, transform returns an empty optional.
#include <iostream>
#include <optional>
int square(int x) { return x * x; }
int main() {
std::optional<int> maybe_int = 10;
auto result = maybe_int.transform(square);
if (result) {
std::cout << "Result: " << *result << '\n';
}
maybe_int = std::nullopt;
result = maybe_int.transform(square);
if (!result) {
std::cout << "Result is empty" << '\n';
}
}This will output:
Result: 100
Result is emptyThese monadic operations make it easier to work with std::optional in a functional style, allowing you to chain operations and handle empty optionals in a clear and concise way.
Nullable Values, std::optional and Monadic Operations
A comprehensive guide to using std::optional to represent values that may or may not be present.