From 7dd25141cdd0c5ce1bc0ccd3c2d9a3c470b63aaf Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 30 Jul 2019 15:31:24 +0200 Subject: [PATCH] Add Error<> Put simply, Error<> is a way of forcing error handling onto an API user. Given a function like: bool might_work(); The following code might have been written previously: might_work(); // but what if it didn't? The easy way to work around this is of course to [[nodiscard]] might_work. But this doesn't work for more complex cases like, for instance, a hypothetical read() function which might return one of _many_ errors (typically signalled with an int, let's say). int might_read(); In such a case, the result is often _read_, but not properly handled. Like: return buffer.substr(0, might_read()); // but what if might_read returned an error? This is where Error<> comes in: typedef Error ReadError; ReadError might_read(); auto res = might_read(); if (might_read.failed()) { switch (res.value()) { case EBADF: ... } } Error<> uses clang's consumable attributes to force failed() to be checked on an Error instance. If it's not checked, then you get smacked. --- AK/Error.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 AK/Error.h diff --git a/AK/Error.h b/AK/Error.h new file mode 100644 index 0000000000..b91721920d --- /dev/null +++ b/AK/Error.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +namespace AK { + +template +class CONSUMABLE(unknown) Error { +public: + RETURN_TYPESTATE(unknown) + Error() + : t(NoErrorValue) + {} + + RETURN_TYPESTATE(unknown) + Error(T t) + : t(t) + {} + + RETURN_TYPESTATE(unknown) + Error(Error&& other) + : t(move(other.t)) + { + } + + RETURN_TYPESTATE(unknown) + Error(const Error& other) + : t(other.t) + { + } + + CALLABLE_WHEN("unknown", "consumed") + ~Error() {} + + SET_TYPESTATE(consumed) + bool failed() const { + return t != NoErrorValue; + } + + [[deprecated]] + SET_TYPESTATE(consumed) + void ignore() {} + + const T& value() const { return t; } + + bool operator==(const Error& o) { return t == o.t; } + bool operator!=(const Error& o) { return t != o.t; } + T t; +}; + +} + +using AK::Error;