Skip to content

Instantly share code, notes, and snippets.

@eliaxelang007
Last active February 4, 2024 22:40
Show Gist options
  • Save eliaxelang007/06506c9b9541d9e0c70409ce6bc2c2c4 to your computer and use it in GitHub Desktop.
Save eliaxelang007/06506c9b9541d9e0c70409ce6bc2c2c4 to your computer and use it in GitHub Desktop.
#include <utility>
#include <functional>
using std::function;
using std::move;
template <typename T, typename E>
class Result {
public:
static Result ok(const T &ok) {
Result result{};
result.tag = Tag::Ok;
result.value.ok = ok;
return result;
}
static Result ok(T &&ok) {
Result result{};
result.tag = Tag::Ok;
result.value.ok = move(ok);
return result;
}
static Result err(const E &err) {
Result result{};
result.tag = Tag::Err;
result.value.err = err;
return result;
}
static Result err(E &&err) {
Result result{};
result.tag = Tag::Err;
result.value.err = move(err);
return result;
}
template <typename M>
M match(
function<M(T)> on_ok,
function<M(E)> on_err
) && {
switch (tag) {
case Tag::Ok: return on_ok(move(value.ok));
case Tag::Err: return on_err(move(value.err));
}
}
Result(const Result& other): tag{other.tag} {
switch (tag) {
case Tag::Ok: { value.ok = other.value.ok; break; }
case Tag::Err: { value.err = other.value.err; break; }
}
}
Result(Result&& other) noexcept: tag{other.tag} {
switch (tag) {
case Tag::Ok: { value.ok = move(other.value.ok); break; }
case Tag::Err: { value.err = move(other.value.err); break; }
}
}
Result& operator=(const Result& other) {
return *this = Result(other);
}
Result& operator=(Result&& other) noexcept {
if (this == &other) return *this;
tag = other.tag;
switch (tag) {
case Tag::Ok: { value.ok = move(other.value.ok); break; }
case Tag::Err: { value.err = move(other.value.err); break; }
}
return *this;
}
~Result() {
switch (tag) {
case Tag::Ok: { value.ok.~T(); break; }
case Tag::Err: { value.err.~E(); break; }
}
}
private:
enum class Tag { Ok, Err } tag;
union Variant {
T ok;
E err;
explicit Variant() {}
Variant(const Variant& other) = delete;
Variant(Variant&& other) noexcept = delete;
Variant& operator=(const Variant& other) = delete;
Variant& operator=(Variant&& other) noexcept = delete;
~Variant() {}
} value;
explicit Result() {}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment