SimplifyC++ Article
C++20 & C++23: The Power of std::variant and std::optional
C++20 & C++23: The Power of std::variant and std::optional
Modern C++ continues to evolve in power, clarity, and expressiveness. Two key tools in this evolution are std::variant and std::optional — both part of the type-safe union and nullable value family, introduced in C++17 and significantly refined in C++20 and C++23.
This article presents a comprehensive guide to the improvements made to these utilities in C++20 and C++23, highlighting real-world use cases, best practices, and what every serious C++ developer should know.
std::optional: Enhancements in C++20 and C++23
Recap: What Is std::optional?
std::optional<int> maybe_value = get_value();if (maybe_value) { std::cout << "Value: " << *maybe_value << '\n';}Represents an optional value, similar to
Optionin Rust orMaybein Haskell.Avoids the pitfalls of null pointers and exception-based returns.
C++20: Improvements to std::optional
constexprSupport You can now usestd::optionalinconstexprcontexts, enabling powerful compile-time evaluations.constexpr std::optional<int> square(int x) {return x > 0 ? std::optional{x * x} : std::nullopt;}static_assert(square(5).value() == 25);Three-Way Comparison (
<=>)std::optionalnow supports the spaceship operator for consistent and simplified comparison behavior.std::optional<int> a = 10, b = 20;if (a < b) { std::cout << "a < b"; }
C++23: Quality-of-Life Enhancements
Monadic Interfaces (proposed) Although not standardized yet, monadic functions like
and_then,transform, andor_elseare being explored to simplify functional-style chaining.Potential future syntax:
maybe_value.and_then([](int v) { return do_something(v); });Improved Debugging and Diagnostics C++23 improves error messages and
constexprfeedback when usingstd::optional, particularly in template-heavy code.
std::variant: Powerful Type-Safe Union
Recap: What Is std::variant?
std::variant<int, std::string> data;data = 42;data = "text";A type-safe alternative to traditional unions.
Enables runtime polymorphism without inheritance.
Excellent for APIs where a value may be one of multiple known types.
C++20: Major Enhancements to std::variant
constexprConstruction and Access Now fully usable in compile-time contexts.constexpr std::variant<int, float> v = 42;static_assert(std::holds_alternative<int>(v));std::visitBecomesconstexprVisitors can now be evaluated at compile time.constexpr int result = std::visit([](auto x) {return x + 1;}, std::variant<int>{5});static_assert(result == 6);Improved Exception Guarantees More operations are marked
noexcept, improving exception safety and performance.
C++23: Subtle but Impactful Improvements
Clearer Diagnostics Template instantiation errors involving variants are now easier to understand.
Better Overload Inference in
std::visitSupports complex lambdas and deduced overloads more gracefully, reducing the need for boilerplate.Library Conformance and Future Compatibility Implementation consistency ensures smoother upgrades and enables future enhancements like reflection and pattern matching.
Real-World Use Cases
Configuration Parsing Use
std::variantto represent config values that could beint,bool, orstring.Command Results Use
std::optional<T>to represent success/failure without exceptions or error codes.Serialization Layers
std::variantmaps well to formats like JSON, YAML, or TOML where values can be heterogeneously typed.
Common Mistakes and Best Practices
| Mistake | Better Approach |
|---|---|
Using .value() unsafely | Check .has_value() or use if (opt) |
Skipping std::visit | Always use std::visit to access variant values |
| Using heavy types in variants | Use smart pointers inside the variant |
Looking Beyond C++23
The next wave of improvements may include:
Pattern Matching (expected in C++26)
Standardized Monadic Interfaces for
optionalandexpectedReflection to make generic programming safer and cleaner
Better Codegen as compilers optimize for variant layout and visitation
Conclusion
With std::optional and std::variant, Modern C++ provides elegant, type-safe alternatives to nullptr, unions, and verbose error handling. The enhancements in C++20 and C++23 bring compile-time power, safer APIs, and cleaner control flow to every C++ codebase.
If you're writing modern C++, these tools are not optional — they are essential. Understanding their capabilities, limitations, and best practices is a mark of true professionalism in contemporary C++ software development.