C++23 - <expected> Header
Last Updated :
22 Sep, 2023
C++23, the next major version of the C++ programming language, brings several exciting features and enhancements. One of the significant additions in C++23 is the <expected> header, which aims to improve error handling and make code more robust and readable. In this article, we will explore the feature of <expected> header, its purpose, and how it simplifies error handling in C++.
Problem with Error Handling
Error handling in C++ has historically been a complex and error-prone task. C++ has exceptions and error codes, but choosing the right approach and implementing error handling consistently across a codebase can be challenging. Additionally, exceptions can introduce performance overhead in certain scenarios.
<expected> Header in C++
The <expected> header in C++23 introduces a new way to handle errors and expected values. It is inspired by similar constructs in other programming languages, such as Rust's Result and Swift's Result types. The primary goal of <expected> is to provide a more explicit and structured way to handle expected values and errors without relying solely on exceptions or error codes.
The <expected> header introduces two main class templates:
- std::expected
- std::unexpected
Let's dive into each of them.
1. std::expected Class Template
The std::expected is a class template in C++ that serves as a mechanism for managing functions that may return either a valid result or an error. It is a wrapper that is particularly useful in scenarios where exceptions might not be the preferred error-handling approach.
Syntax
The std::expected is used as the value return by the function as shown below:
std::expected<T, E> function_name {
// statements
}
where,
- T: This parameter represents the type of the expected (valid) value that the function may return when it succeeds.
- E: This parameter represents the type of error condition that the function may return when it fails.
When a function returns an instance of std::expected, the caller can easily check whether the result is valid (contains a value of type T) or represents an error (contains an error of type E). This approach provides a clear and structured way to handle errors in a functional, non-exception-based manner.
std::expected Member Functions
Following are some commonly used Member functions of the std::expected class:
S.No.
| Function
| Description
|
---|
1
| value() | It allows you to retrieve the stored value of type T. |
---|
2
| error() | This one facilitates access to the stored error of type E. |
---|
3
| has_value(): | This member function is used to inquire whether the std::expected contains a value or not. It returns true if the std::expected holds a value and false if it holds an error. |
---|
4
| error_code() | When applicable, this member function is employed to convert the stored error into an error code. |
---|
2. std::unexpected Class Template
The std::unexpected is not a standalone class but rather a concept used with std::expected. It helps to define how unexpected errors are handled within a specific context.
When an unexpected error occurs within a function that returns a std::expected, the function can use std::unexpected to specify what action should be taken. This allows developers to define a custom response to unexpected errors.
Syntax
std::expected<T, E> function_name {
// statements
return std::unexpected< E >(some_value);
}
where,
- E: The error type specified in std::expected template.
How to use std::expected?
To use the std::expected class template, follow the given steps:
- Create an instance of std::expected with the expected value type (T) and the error type (E).
- In case of an error, return an instance of std::expected with the error type (E).
- When an operation succeeds, return an instance of std::expected with the expected value (T).
- Utilize methods like has_value() and value() to access the value or error() to obtain the error, as needed.
Examples
Below given is the example code that uses expected in C++:
Example 1: Handling a Successful Division
C++
// C++ program to illustrate the successful execution using
// std::expected feature
#include <expected>
#include <iostream>
using namespace std;
// defining function to return the std::expected object
expected<int, string> divide(int a, int b)
{
if (b == 0) {
// return value in case of exception
return unexpected<string>("Division by zero");
}
// return value when execution is successful
return a / b;
}
// driver code
int main()
{
auto result = divide(10, 2);
// printing result based on the value of std::expected
if (result.has_value()) {
cout << "Result: " << result.value() << endl;
}
else {
cerr << "Error: " << result.error() << endl;
}
return 0;
}
Output
Result: 5
In this example, the divide function returns a std::expected<int, std::string>, representing the result of division or an error message for division by zero.
Example 2: Handling Division by Zero
C++
// C++ program to illustrate the successful execution using
// std::expected feature
#include <expected>
#include <iostream>
using namespace std;
// defining function to return the std::expected object
expected<int, string> divide(int a, int b)
{
if (b == 0) {
// return value in case of exception
return unexpected<string>("Division by zero");
}
// return value when execution is successful
return a / b;
}
// driver code
int main()
{
auto result = divide(10, 0);
// printing result based on the value of std::expected
if (result.has_value()) {
cout << "Result: " << result.value() << endl;
}
else {
cerr << "Error: " << result.error() << endl;
}
return 0;
}
Output
Error: Division by zero
Example 3: Using a Different Error Type
C++
// C++ program to illustrate the behaviour of std::expected
// for different type
#include <expected>
#include <iostream>
using namespace std;
expected<int, float> divideWithFloatError(int a, int b)
{
if (b == 0) {
// Different error type
return unexpected<float>(0.0f);
}
return a / b;
}
// Driver code
int main()
{
auto result3 = divideWithFloatError(6, 0);
if (result3.has_value()) {
cout << "Result 3: " << result3.value() << endl;
}
else {
cerr << "Error 3: " << result3.error() << endl;
}
return 0;
}
Output
Error 3: 0
Advantages of using std::expected
The <expected> header brings forth a multitude of benefits:
- std::expected makes error handling simple and concise within code. It distinctly separates the expected and error scenarios.
- The C++ type system ensures that you cannot inadvertently mix up expected values and errors.
- std::Expected is designed with minimal performance overhead, ensuring efficient error handling.
Conclusion
The <expected> header in C++23 represents a significant leap forward in error handling for C++ developers. With improved code clarity, type safety, and performance characteristics, it offers an efficient solution for handling expected values and errors gracefully.
Similar Reads
C++ Programming Language C++ is a computer programming language developed by Bjarne Stroustrup as an extension of the C language. It is known for is fast speed, low level memory management and is often taught as first programming language. It provides:Hands-on application of different programming concepts.Similar syntax to
5 min read
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Spring Boot Tutorial Spring Boot is a Java framework that makes it easier to create and run Java applications. It simplifies the configuration and setup process, allowing developers to focus more on writing code for their applications. This Spring Boot Tutorial is a comprehensive guide that covers both basic and advance
10 min read
Object Oriented Programming in C++ Object Oriented Programming - As the name suggests uses objects in programming. Object-oriented programming aims to implement real-world entities like inheritance, hiding, polymorphism, etc. in programming. The main aim of OOP is to bind together the data and the functions that operate on them so th
5 min read
Class Diagram | Unified Modeling Language (UML) A UML class diagram is a visual tool that represents the structure of a system by showing its classes, attributes, methods, and the relationships between them. It helps everyone involved in a projectâlike developers and designersâunderstand how the system is organized and how its components interact
12 min read
Backpropagation in Neural Network Back Propagation is also known as "Backward Propagation of Errors" is a method used to train neural network . Its goal is to reduce the difference between the modelâs predicted output and the actual output by adjusting the weights and biases in the network.It works iteratively to adjust weights and
9 min read
3-Phase Inverter An inverter is a fundamental electrical device designed primarily for the conversion of direct current into alternating current . This versatile device , also known as a variable frequency drive , plays a vital role in a wide range of applications , including variable frequency drives and high power
13 min read
30 OOPs Interview Questions and Answers [2025 Updated] Object-oriented programming, or OOPs, is a programming paradigm that implements the concept of objects in the program. It aims to provide an easier solution to real-world problems by implementing real-world entities such as inheritance, abstraction, polymorphism, etc. in programming. OOPs concept is
15 min read
Polymorphism in Java Polymorphism in Java is one of the core concepts in object-oriented programming (OOP) that allows objects to behave differently based on their specific class type. The word polymorphism means having many forms, and it comes from the Greek words poly (many) and morph (forms), this means one entity ca
7 min read
What is Vacuum Circuit Breaker? A vacuum circuit breaker is a type of breaker that utilizes a vacuum as the medium to extinguish electrical arcs. Within this circuit breaker, there is a vacuum interrupter that houses the stationary and mobile contacts in a permanently sealed enclosure. When the contacts are separated in a high vac
13 min read