@ -11,13 +11,24 @@
# include "util.hh"
# include "util.hh"
# define _EO_DEFEXCEPT_BASIC_(NAME, BASE, ...) class NAME : public ::exopt:: BASE { \
constexpr static inline auto MESSSAGE = ( __VA_ARGS__ ) ; \
public : \
_EO_CLASS_DEFINE ( NAME , constexpr , noexcept , virtual , = default ) ; \
constexpr virtual std : : string_view message ( ) const noexcept override { return { MESSAGE } ; } \
}
# define _EO_DEFEXCEPT_BASIC(NAME, MSG) _EO_DEFEXCEPT_BASIC_(NAME, Error, MSG)
# define _EO_DEFEXCEPT_TRACE_BASIC(NAME, MSG) _EO_DEFEXCEPT_BASIC_(NAME, TracedError, MSG)
namespace exopt {
namespace exopt {
// Report generated from an error. (virtual base, not abstract.)
// Report generated from an error. (virtual base, not abstract.)
class Report {
class Report {
public :
public :
virtual ~ Report ( ) ;
virtual ~ Report ( ) ;
} ;
} ;
// This is propagated returned (base, abstract)
// This is base thrown (base, abstract)
class Error {
class Error {
public :
public :
constexpr Error ( Error const & ) = default ;
constexpr Error ( Error const & ) = default ;
@ -25,6 +36,9 @@ namespace exopt {
constexpr Error & operator = ( Error & & ) = default ;
constexpr Error & operator = ( Error & & ) = default ;
constexpr Error & operator = ( Error const & ) = default ;
constexpr Error & operator = ( Error const & ) = default ;
virtual types : : Box < TracedError > into_traced ( std : : stacktrace trace & & ) & & noexcept ; // = std::stacktrace::current()) && noexcept;
inline typed : : Box < TracedError > into_traced ( std : : stacktrace trace = std : : stacktrace : : current ( ) ) & & noexcept
{ return std : : move ( * this ) . into_traced ( std : : move ( trace ) ) ; }
constexpr virtual std : : source_location const & location ( ) const noexcept { return m_location ; }
constexpr virtual std : : source_location const & location ( ) const noexcept { return m_location ; }
@ -32,8 +46,9 @@ namespace exopt {
constexpr virtual std : : string_view message ( ) const noexcept = 0 ;
constexpr virtual std : : string_view message ( ) const noexcept = 0 ;
constexpr virtual types : : Option < Error & > inner ( ) noexcept { return { std : : nullopt } ; }
//constexpr virtual types::Option<Error&> inner() noexcept { return { std::nullopt }; }
constexpr virtual types : : MaybeOwned < Report > into_report ( ) noexcept { /* TODO */ } //TODO: Maybe just use `std::optional<std::reference_wrapper<Error>>`? Or Box<Report&>?
constexpr virtual types : : Option < Error const & > inner ( ) const noexcept { return { std : : nullopt } ; }
constexpr virtual types : : MaybeOwned < Report > into_report ( ) & noexcept { /* TODO */ } //TODO: Maybe just use `std::optional<std::reference_wrapper<Error>>`? Or Box<Report&>?
constexpr virtual types : : MaybeOwned < Report > into_report ( ) & & noexcept { /* TODO: auto{*this}.into_report() */ }
constexpr virtual types : : MaybeOwned < Report > into_report ( ) & & noexcept { /* TODO: auto{*this}.into_report() */ }
constexpr virtual ~ Error ( ) = default ;
constexpr virtual ~ Error ( ) = default ;
@ -47,7 +62,7 @@ namespace exopt {
} ;
} ;
// This is propagated returned, along with a stack trace. (base, abstract)
// This is propagated returned, along with a stack trace. (base, abstract)
class TracedError : Error {
class TracedError : public Error {
public :
public :
TracedError ( TracedError const & ) = default ;
TracedError ( TracedError const & ) = default ;
TracedError ( TracedError & & ) = default ;
TracedError ( TracedError & & ) = default ;
@ -62,13 +77,27 @@ namespace exopt {
std : : source_location loc = std : : source_location : : current ( )
std : : source_location loc = std : : source_location : : current ( )
, std : : stacktrace trace = std : : stacktrace : : current ( ) ) noexcept
, std : : stacktrace trace = std : : stacktrace : : current ( ) ) noexcept
: Error ( std : : move ( loc ) ) , m_trace ( std : : move ( trace ) ) { }
: Error ( std : : move ( loc ) ) , m_trace ( std : : move ( trace ) ) { }
/*inline TracedError(
std : : stacktrace & & trace ,
, std : : source_location loc = std : : source_location : : current ( ) ) noexcept
: Error ( std : : move ( loc ) ) , m_trace ( std : : move ( trace ) ) { } */
inline TracedError (
std : : stacktrace & & trace ,
, std : : source_location & & loc ) noexcept
: Error ( std : : move ( loc ) ) , m_trace ( std : : move ( trace ) ) { }
private :
private :
inline types : : Box < TracedError > into_traced ( std : : stacktrace trace & & ) & & noexcept override final // = std::stacktrace::current()) && noexcept;
{ return typed : : Box < TracedError > { std : : move ( * this ) } ; } //TODO: XXX: How to check if `this` is *already* boxed? This dynamic double-boxing is inefficient, but also can probably not be checked unless relying on enabling RTTI by default
inline typed : : Box < TracedError > into_traced ( std : : stacktrace trace = std : : stacktrace : : current ( ) ) & & noexcept override final
{ return typed : : Box < TracedError > { std : : move ( * this ) } ; }
std : : stacktrace m_trace ; //TODO: Maybe box this? idk how big it is...
std : : stacktrace m_trace ; //TODO: Maybe box this? idk how big it is...
} ;
} ;
#if 0
// This is thrown. (virtual base, abstract)
// This is thrown. (virtual base, abstract)
class Panic : /*virtual?? I think it should be XXX*/ Error {
class Panic : /*virtual?? I think it should be XXX*/ Error {
//TODO: How to make a `constexpr` deduced panic that has stack-trace at runtime only? Is it needed? Hnm...
//TODO: How to make a `constexpr` deduced panic that has stack-trace at runtime only? Is it needed? Hnm...
} ;
} ;
//TODO: Fatal(string) : public virtual Panic
//TODO: Fatal(string) : public virtual Panic
# endif
}
}