// SPDX-License-Identifier: BSD-2-Clause // author: Max Kellermann #ifndef EXCEPTION_HXX #define EXCEPTION_HXX #include #include #include /** * Throws the specified exception. There is an overload for * std::exception_ptr which throws the contained exception instead of * the std::exception_ptr itself. */ template [[noreturn]] inline void ThrowException(T &&t) { throw std::forward(t); } [[noreturn]] inline void ThrowException(std::exception_ptr ep) { std::rethrow_exception(ep); } /** * Create a nested exception, wrapping #ep inside the * std::current_exception(). */ template inline std::exception_ptr NestCurrentException(T &&t) noexcept { try { std::throw_with_nested(std::forward(t)); } catch (...) { return std::current_exception(); } } /** * Create a nested exception, wrapping #ep inside (a copy of) #t. */ template inline std::exception_ptr NestException(std::exception_ptr ep, T &&t) noexcept { try { std::rethrow_exception(ep); } catch (...) { return NestCurrentException(std::forward(t)); } } /** * Find an instance of #T in the nested exception chain, and return a * pointer. Returns nullptr if no such instance was found. */ template [[gnu::pure]] inline const T * FindNested(std::exception_ptr ep) noexcept { try { std::rethrow_exception(ep); } catch (const T &t) { return &t; } catch (const std::nested_exception &ne) { return FindNested(ne.nested_ptr()); } catch (...) { } return nullptr; } /** * Find an instance of #T in the nested exception chain, and rethrow * it. Does nothing if no such instance was found. */ template inline void FindRetrowNested(std::exception_ptr ep) { try { std::rethrow_exception(ep); } catch (const T &t) { throw; } catch (const std::nested_exception &ne) { FindRetrowNested(ne.nested_ptr()); } catch (...) { } } /** * Obtain the full concatenated message of an exception and its nested * chain. */ std::string GetFullMessage(const std::exception &e, const char *fallback="Unknown exception", const char *separator="; ") noexcept; /** * Obtain the full concatenated message of an exception and its nested * chain. */ std::string GetFullMessage(std::exception_ptr ep, const char *fallback="Unknown exception", const char *separator="; ") noexcept; #endif