mijin2/source/mijin/util/exception.hpp

78 lines
1.7 KiB
C++

#pragma once
#ifndef MIJIN_UTIL_EXCEPTION_HPP_INCLUDED
#define MIJIN_UTIL_EXCEPTION_HPP_INCLUDED 1
#include <stdexcept>
#include "../debug/stacktrace.hpp"
namespace mijin
{
//
// public defines
//
//
// public types
//
class Exception : public std::runtime_error
{
private:
Result<Stacktrace> stacktrace_;
std::exception_ptr cause_;
public:
Exception(const std::string& what) : std::runtime_error(what), stacktrace_(captureStacktrace(1)), cause_(std::current_exception()) {}
Exception(const char* what) : Exception(std::string(what)) {}
[[nodiscard]]
const Result<Stacktrace>& getStacktrace() const noexcept { return stacktrace_; }
[[nodiscard]]
const std::exception_ptr& getCause() const noexcept { return cause_; }
};
//
// public functions
//
template<typename TCondition, typename TException = std::runtime_error, typename... TExceptionArgs>
inline decltype(auto) ensure(TCondition&& condition, TExceptionArgs&&... args)
{
if (!static_cast<bool>(std::forward<TCondition>(condition)))
{
throw TException(std::forward<TExceptionArgs>(args)...);
}
return std::forward<TCondition>(condition);
}
template<typename TFunc>
void walkExceptionCause(const std::exception_ptr& cause, TFunc func)
{
if (cause)
{
try
{
std::rethrow_exception(cause);
}
catch(Exception& exc)
{
func(exc);
walkExceptionCause(exc.getCause(), std::move(func));
}
catch(std::exception& exc)
{
func(exc);
}
catch(...)
{
func(nullptr);
}
}
}
} // namespace mijin
#endif // MIJIN_UTIL_EXCEPTION_HPP_INCLUDED