TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #911 4.07K
Возврат ошибки. std::expected
#опытным

В С++23 появился практически идеальный класс для работы с объектами ошибки - std::expected.

Это та самая обертка над вариантом с приятным интерфейсом, о котором говорилось в прошлом посте.

struct Error {
std::string message;
};

std::expected<double, Error> safe_divide(double a, double b) {
if (b == 0.0) { // здесь нужна нормальная проверка на равенство с epsilon
return std::unexpected(Error{"Division by zero"});
}
return a / b;
}

auto div_result = safe_divide(10.0, 2.0);

if (div_result.has_value()) {
std::cout << "Result: " << div_result.value() << std::endl;
} else {
std::cout << "Error: " << div_result.error().message << std::endl;
}
// или с операторами
if (div_result) { // operator bool
std::cout << "Result: " << *div_result << std::endl; // operator*
} else {
std::cout << "Error: " << div_result.error().message << std::endl;
}


По сути у std::expected в базовом интерефейсе 3 метода и пара операторов. Методы has_value(), value() и error() для проверки и доступа к значению или ошибке. И operator bool, operator*, operator-> для ленивых со сточенными пальцами;

Преимущества нового типа std::expected по сравнению с std::variant:

✅ Хранит только два типа: значение и ошибка.

✅ Делает код интуитивно понятнее, поскольку для создания ошибки нужно использовать std::unexpected. Это особенно удобно, когда тип ошибки std::string. В этом случае использование std::unexpected{ "Something bad happens" } позволяет явно обозначить в коде, что мы не просто строку возвращаем, а сообщение об ошибке.

✅ Предоставляет простой и лаконичный базовый интерфейс: 3 метода и пара операторов. Методы has_value(), value() и error() для проверки и доступа к значению или ошибке. И operator bool, operator*, operator->, кому лень писать названия методов.

С std::expeсted удобно работать, если есть всего один тип результата и один тип ошибки. Работать с std::expected<std::variant<Type1, Type2>, Error> или std::expected<Type, std::variant<Error1, Error2>> не так удобно, как просто с вариантом из трех типов. Если нужно возвращать больше ошибок, то можно пользоваться разными вариантами кодов ошибки от enuma'а до std::error_code или даже просто строкой.

Must have при работе без исключений.

Use a right semantic. Stay cool.

#cpp23
  • 🔥 26
  • ❤ 15
  • 👍 11
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →