![]() |
VOOZH | about |
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++.
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.
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:
Let's dive into each of them.
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.
The std::expected is used as the value return by the function as shown below:
std::expected<T, E> function_name {
// statements
}where,
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.
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. |
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.
std::expected<T, E> function_name {
// statements
return std::unexpected< E >(some_value);
}
where,
To use the std::expected class template, follow the given steps:
Below given is the example code that uses expected in C++:
Example 1: Handling a Successful Division
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
Output
Error: Division by zero
Example 3: Using a Different Error Type
Output
Error 3: 0
The <expected> header brings forth a multitude of benefits:
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.