Nullable Values using std::optional

Monadic operations with std::optional

Can you explain and provide examples of the monadic operations available for std::optional in C++23?

Illustration representing computer hardware

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.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved