Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Monadic operations for std::optional

Use case

Chain operations that might fail.

Explanation

transform = apply functions, wrap result in optional (if empty, stays empty). and_then = apply function that returns optional, flatten result (avoids optional<optional<T>>). or_else = provide fallback if empty. No more nested if (opt.has_value()) checks.

Code

#include <cstdint>
#include <optional>
#include <print>
#include <string>

std::optional<uint64_t> findSymbol(const std::string &name) {
  if (name == "_main")
    return 0x10001000;
  return std::nullopt;
}

std::optional<std::string> demangleName(uint64_t addr) {
  if (addr == 0x10001000)
    return "main";
  return std::nullopt;
}

int main() {
  auto result =
      findSymbol("_main")
          .transform([](uint64_t addr) { return addr + 0x10; })
          .and_then([](uint64_t addr) { return demangleName(addr - 0x10); })
          .or_else([]() -> std::optional<std::string> { return "unknown"; });

  std::println("Result: {}", *result);

  return 0;
}

View on GitHub.

Output

$ ./src/c++23/build/monadic-operations
Result: main