When should I use std::expected
and when should I use exceptions? Take this function for example:
int parse_int(std::string_view str) {
if (str.empty()) {
throw std::invalid_argument("string must not be empty");
}
/* ... */
if (/* result too large */) {
throw std::out_of_range("value exceeds maximum for int");
}
return result;
}
I want to distinguish between different errors when using this function, so it's useful that I can throw different types of exceptions. However, I could also do that with std::expected
:
enum class parse_error {
empty_string,
invalid_format,
out_of_range
};
std::expected<int, parse_error> parse_int(std::string_view str) noexcept {
if (str.empty()) {
return std::unexpected(parse_error::empty_string);
}
/* ... */
if (/* result too large */) {
return std::unexpected(parse_error::out_of_range);
}
return result;
}
Are there any reasons to use std::expected
over exceptions (performance, code size, compile speed, ABI), or is it just stylistic preference?
std::expected
does not change those approaches. – Bankrollstd::expected
. 1. you have syntax sugar thanks tostd::expected
being convertible tobool
, so your code is still clean; 2. You use the return type, you don't return just a status code. 3. You can carry as much information as you want; 4. still applies. IMO error handling withstd::expected
is distinct from simply return a status code. – Diverticulumstd::expected
is just a struct. You are right, it's just a sugar. Nothing new can be added to the linked answers "when to use". – Bankrollstd::expected
. Binary size is likely smaller withstd::expected
. Your ability to respond to every possible error only exists withstd::expected
. – Miss