Changed error system to CRTP, rough draft
This commit is contained in:
+60
-24
@@ -5,48 +5,84 @@
|
||||
#include <exception>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace nb {
|
||||
|
||||
typedef std::unordered_map<unsigned int, const char*> ErrorCodeMap;
|
||||
|
||||
class Error : public std::exception {
|
||||
template<class ErrorType>
|
||||
class ErrorBase : public std::exception {
|
||||
public:
|
||||
Error(const unsigned int code=0, std::exception* const trace=nullptr) noexcept;
|
||||
Error(std::string, std::exception* const=nullptr) noexcept;
|
||||
Error(const Error&) noexcept;
|
||||
static std::string lookup(unsigned int);
|
||||
|
||||
virtual const char* what() const noexcept override final {
|
||||
return static_cast<const ErrorType*>(this)->_msg.c_str();
|
||||
};
|
||||
unsigned int code() const noexcept {
|
||||
return static_cast<const ErrorType*>(this)->_code;
|
||||
};
|
||||
|
||||
unsigned int code() const noexcept;
|
||||
virtual const char* type() const noexcept final;
|
||||
virtual const char* what() const noexcept override final;
|
||||
|
||||
template<typename NBError>
|
||||
friend const char* ErrorCodeLookup(unsigned int);
|
||||
protected:
|
||||
static const ErrorCodeMap ErrorCodes;
|
||||
Error(
|
||||
const unsigned int,
|
||||
std::string,
|
||||
std::exception* const,
|
||||
ErrorBase() = default;
|
||||
ErrorBase(
|
||||
const unsigned int code,
|
||||
std::string msg,
|
||||
std::exception* const trace,
|
||||
unsigned int line=0,
|
||||
std::string filename=""
|
||||
) noexcept;
|
||||
) noexcept : _code{code} {
|
||||
static_assert(std::is_same<const std::unordered_map<unsigned int, const char*>, decltype(ErrorType::ErrorMessages)>::value,
|
||||
"const std::unordered_map<unsigned int, const char*> ErrorMessages must be "
|
||||
"a class member."
|
||||
);
|
||||
static_assert(std::is_enum_v<typename ErrorType::ErrorCodes>, "enum ErrorCodes must be a class member.");
|
||||
static_assert(std::is_same<std::underlying_type_t<typename ErrorType::ErrorCodes>, unsigned int>::value,
|
||||
"enum ErrorCodes must be of underlying type unsigned int."
|
||||
);
|
||||
static_assert(std::is_same<const std::string, decltype(ErrorType::type)>::value,
|
||||
"const std::string type must be a class member."
|
||||
);
|
||||
|
||||
_msg = std::string(ErrorType::type);
|
||||
_msg += ":" + std::to_string(code);
|
||||
if (line && filename.size()) {
|
||||
_msg += " in \'" + filename + "\':" + std::to_string(line);
|
||||
}
|
||||
_msg += "\n\t" + msg;
|
||||
if (trace) {
|
||||
_msg += "\nTraceback - " + std::string(trace->what());
|
||||
}
|
||||
}
|
||||
|
||||
const char* _type;
|
||||
const unsigned int _code;
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
template<typename NBError>
|
||||
const char* ErrorCodeLookup(unsigned int code) {
|
||||
for (auto kv : NBError::ErrorCodes) {
|
||||
if (kv.first == code) {
|
||||
return kv.second;
|
||||
}
|
||||
|
||||
class Error : public ErrorBase<Error> {
|
||||
public:
|
||||
Error(unsigned int code, std::exception* const trace=nullptr)
|
||||
: ErrorBase<Error>(code, ErrorBase<Error>::lookup(code), trace) {}
|
||||
|
||||
enum ErrorCodes : unsigned int {
|
||||
UNDEFINED, BADERRORCODE
|
||||
};
|
||||
static const std::string type;
|
||||
static const ErrorCodeMap ErrorMessages;
|
||||
|
||||
};
|
||||
|
||||
template<class ErrorType>
|
||||
std::string ErrorBase<ErrorType>::lookup(unsigned int code) {
|
||||
for (auto kv : ErrorType::ErrorMessages) {
|
||||
if (kv.first==code) {
|
||||
return std::string(kv.second);
|
||||
}
|
||||
}
|
||||
|
||||
throw Error(666);
|
||||
throw Error(Error::ErrorCodes::BADERRORCODE);
|
||||
}
|
||||
|
||||
} // namespace nb
|
||||
|
||||
Reference in New Issue
Block a user