5

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?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
  • IMHO it's a dupe of https://stackoverflow.com/questions/4670987/why-is-it-better-to-throw-an-exception-rather-than-return-an-error-code and https://stackoverflow.com/questions/1849490/c-arguments-for-exceptions-over-return-codes. `std::expected` does not change those approaches. – 273K Jun 12 '23 at 22:29
  • 3
    @273K some of the issues with status codes in the top answer don't apply to `std::expected`. 1. you have syntax sugar thanks to `std::expected` being convertible to `bool`, 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 with `std::expected` is distinct from simply return a status code. – Jan Schultke Jun 12 '23 at 22:33
  • `std::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". – 273K Jun 12 '23 at 22:37
  • Now that this question is closed, performance is reliably better with `std::expected`. Binary size is likely smaller with `std::expected`. Your ability to respond to every possible error only exists with `std::expected`. – Drew Dormann Jun 12 '23 at 23:06

0 Answers0