Daily bit(e) C++. std::current_exception, std::exception_ptr, std::rethrow_exception
Добавлено 14 сентября 2026 в 04:08
Daily bit(e) C++ 106, использование механизмов сохранения и повторного выброса исключений (появившихся в C++11) при реализации корутин.

При реализации корутин необходимо решить, как именно обрабатывать исключения.
Один из вариантов – игнорировать исключения и завершить выполнение программы методом unhandled_exception().
В качестве альтернативы можно воспользоваться механизмами сохранения и повторного выброса исключений, доступными в C++11:
std::current_exceptionstd::exception_ptrstd::rethrow_exception
#include <iostream>
#include <coroutine>
#include <exception>
template <typename Result>
struct Promise;
// Тип результата
template <typename Result>
struct Task : std::coroutine_handle<Promise<Result>>
{
using promise_type = Promise<Result>;
~Task()
{
this->destroy();
}
Result& get_value()
{
// если корутина завершилась исключением,
// выбросить исключение повторно
if (this->promise().exception_)
std::rethrow_exception(this->promise().exception_);
// иначе, вернуть результат
return this->promise().value_;
}
};
// Тип промис
template <typename Result>
struct Promise
{
Task<Result> get_return_object()
{
return {Task<Result>::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept
{
return {};
}
std::suspend_always final_suspend() noexcept
{
return {};
}
void return_value(auto&& val)
{ // сохранить результат
value_ = std::forward<decltype(val)>(val);
}
void unhandled_exception()
{ // сохранить исключение
exception_ = std::current_exception();
}
Result value_;
std::exception_ptr exception_;
};
Task<int> coro_success()
{
co_return 1;
}
Task<int> coro_throws()
{
throw std::runtime_error("Failed.");
co_return 2;
}
try
{
auto c1 = coro_success();
c1.resume(); // дать корутине выполниться
std::cout << c1.get_value() << "\n";
// напечатает "1"
auto c2 = coro_throws();
c2.resume(); // дать корутине выполниться
std::cout << c2.get_value() << "\n";
// c2.get_value() повторно выбрасывает исключение
}
catch (const std::exception& e)
{
// e.what() == "Failed."
std::cout << e.what() << "\n";
}
