aboutsummaryrefslogtreecommitdiff
path: root/libk
diff options
context:
space:
mode:
Diffstat (limited to 'libk')
-rw-r--r--libk/makefile3
-rw-r--r--libk/result.h23
-rw-r--r--libk/test/result.cc16
-rw-r--r--libk/test/string.cc (renamed from libk/string/test.cc)0
-rw-r--r--libk/test/types.cc (renamed from libk/types/test.cc)7
-rw-r--r--libk/types.h6
6 files changed, 53 insertions, 2 deletions
diff --git a/libk/makefile b/libk/makefile
index 966caae..afea066 100644
--- a/libk/makefile
+++ b/libk/makefile
@@ -1,4 +1,5 @@
CXX_OBJ += libk/string/string.o libk/string/integerview.o \
libk/stdlib/abort.o libk/stdlib/console.o
-CXX_TEST_OBJ += libk/types/test.o libk/string/test.o
+
+CXX_TEST_OBJ += libk/test/types.o libk/test/string.o libk/test/result.o
diff --git a/libk/result.h b/libk/result.h
new file mode 100644
index 0000000..8077baf
--- /dev/null
+++ b/libk/result.h
@@ -0,0 +1,23 @@
+#pragma once
+#include <types.h>
+
+// TODO T&& constructor
+// TODO T&& Result::take() with consumed semantics
+
+template <typename T, error_enum_t E>
+class Result {
+public:
+ explicit constexpr Result(T t) : is_ok(true), data{.t = t} {};
+ explicit constexpr Result(E e) : is_ok(false), data{.e = e} {};
+
+ constexpr operator bool() const { return is_ok; }
+ constexpr E error() const { return is_ok ? E::NoError : data.e; }
+ constexpr T value() const { return is_ok ? data.t : T{}; }
+
+private:
+ const bool is_ok;
+ union {
+ T t;
+ E e;
+ } data;
+};
diff --git a/libk/test/result.cc b/libk/test/result.cc
new file mode 100644
index 0000000..be93a07
--- /dev/null
+++ b/libk/test/result.cc
@@ -0,0 +1,16 @@
+#include <result.h>
+
+enum ErrorX { one, two = 5, three, NoError };
+
+// operator bool
+static_assert(!(Result<int, ErrorX>{ErrorX::one}));
+static_assert(!(Result<int, ErrorX>{ErrorX::two}));
+static_assert((Result<int, ErrorX>{5}));
+
+// error
+static_assert((Result<int, ErrorX>{ErrorX::one}).error() == ErrorX::one);
+static_assert((Result<int, ErrorX>{5}).error() == ErrorX::NoError);
+
+// value
+static_assert((Result<int, ErrorX>{ErrorX::one}).value() == int{});
+static_assert((Result<int, ErrorX>{5}).value() == 5);
diff --git a/libk/string/test.cc b/libk/test/string.cc
index 4d7d340..4d7d340 100644
--- a/libk/string/test.cc
+++ b/libk/test/string.cc
diff --git a/libk/types/test.cc b/libk/test/types.cc
index b3f29d9..3686a78 100644
--- a/libk/types/test.cc
+++ b/libk/test/types.cc
@@ -49,3 +49,10 @@ static_assert(libk::is_unsigned<int8_t>() == false);
static_assert(libk::is_unsigned<int16_t>() == false);
static_assert(libk::is_unsigned<int32_t>() == false);
static_assert(libk::is_unsigned<int64_t>() == false);
+
+// error_enum_t
+enum EnumX { x, y, z };
+enum ErrorX { one, two, three, NoError };
+
+static_assert(!libk::error_enum_t<EnumX>);
+static_assert(libk::error_enum_t<ErrorX>);
diff --git a/libk/types.h b/libk/types.h
index 7f16206..3e728fb 100644
--- a/libk/types.h
+++ b/libk/types.h
@@ -35,7 +35,7 @@ typedef long long int int64_t;
constexpr int64_t int64_t_max = uint64_t_max / 2;
constexpr int64_t int64_t_min = -int64_t_max - 1;
-// Type Traits
+/* Type Traits */
template <class T, T v>
struct integral_constant {
@@ -54,3 +54,7 @@ struct is_same<T, T> : integral_constant<bool, true> {};
/* is_unsigned */
template <typename T>
struct is_unsigned : integral_constant<bool, (T{0} < static_cast<T>(-1))> {};
+
+/* error enum concept */
+template <typename T>
+concept error_enum_t = (__is_enum(T) && requires { T::NoError; });