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 empty
or_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: 42
transform()
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 empty
These 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.
Answers to questions are automatically generated and may not have been reviewed.
std::optional
A comprehensive guide to using std::optional
to represent values that may or may not be present.