1. Revision History
1.1. R1
-
Example now uses
std :: expected < void , std :: string > -
Use shorter wording as suggested by Daniel Krügler
-
Added SG10 recommendation to bump
__cpp_lib_expected -
Added acknowledgements
2. Motivation
Today,
provides a
member function that can be used to check whether the instance holds a value or an error.
There is also an implicit conversion operator to
that can be used for the same purpose.
These two existing mechanisms follow several other facilities in the language, including
.
While
provides only the
member function as its primary state-checking mechanism,
serves a fundamentally different purpose.
Unlike
, which represents either a value or nothing,
represents either a value or an error.
This semantic difference warrants distinct interface considerations.
Adding
creates symmetry in the API that better reflects the dual-state nature of
and provides more readable, self-documenting code when the focus is on error handling rather than value presence.
In case of
partial specialization of
,
member function is obscure, because
doesn’t represent a value on its own.
In the meantime
would be clear and more understandable.
2.1. Sample usecase
Consider the following examples (assuming
is of type
):
Without this proposal | With this proposal |
|
|
|
|
2.2. Impact on the standard
This change is entirely based on library extensions and does not require any language features beyond what is available in C++ 23.
2.3. Other languages
It might be unexpected to not have a
method in
, especially when moving from other languages that have similar constructs.
The proposed approach is consistent with similar facilities in some other programming languages:
-
Rust provides both
andis_ok ()
methods on itsis_err ()
type.Result -
D provides both
andhasValue
properties in itshasError
package.expected -
Haskell provides
andisRight
in itsisLeft
type.Either
These implementations acknowledge the dual-state nature of error-handling types by offering explicit methods for checking both states, rather than relying solely on negation of a value-checking method.
3. Proposed Wording
3.1. Feature test macro
Bump the
value in 17.3.2 [version.syn]:
#define __cpp_lib_execution 201902L // also in <execution> #define __cpp_lib_expected 202211L // also in <expected> #define __cpp_lib_expected 20yymmL // also in <expected> #define __cpp_lib_filesystem 201703L // also in <filesystem>
3.2. Expected object
In 22.8.6.1 [expected.object.general] add:
constexpr bool has_value () const noexcept ; constexpr bool has_error () const noexcept ; constexpr const T & value () const & ;
In 22.8.6.6 [expected.object.obs] add after ❡7:
constexpr bool has_error () const noexcept ; Effects : Equivalent to : return ! has_value ();
3.3. Expected void
In 22.8.7.1 [expected.void.general] add:
constexpr bool has_value () const noexcept ; constexpr bool has_error () const noexcept ; constexpr void operator * () const noexcept ;
In 22.8.7.6 [expected.void.obs] add after ❡1:
constexpr bool has_error () const noexcept ; Effects : Equivalent to : return ! has_value ();
4. Acknowledgements
We would like to thank Bronek Kozicki and Gašper Ažman for reviewing the initial draft and providing early feedback, as well as Daniel Krügler for recommending the use of shorthand syntax for "Equivalent to" in the wording.