diff options
Diffstat (limited to 'libk')
-rw-r--r-- | libk/makefile | 3 | ||||
-rw-r--r-- | libk/result.h | 23 | ||||
-rw-r--r-- | libk/test/result.cc | 16 | ||||
-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.h | 6 |
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; }); |