summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-20 15:35:55 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-20 15:35:55 +0100
commit80b18cc979fcb1e772e5b7c7d45aa72602d461d7 (patch)
tree266cf3a6b23ac8f4d903a238f063b87354e231ea /asl
parent0f2d186fbd4cc637a359b1d62370174aebd2b80f (diff)
More work on option
Diffstat (limited to 'asl')
-rw-r--r--asl/meta_tests.cpp8
-rw-r--r--asl/option.hpp77
-rw-r--r--asl/option_tests.cpp26
-rw-r--r--asl/test_types.hpp4
4 files changed, 106 insertions, 9 deletions
diff --git a/asl/meta_tests.cpp b/asl/meta_tests.cpp
index be0c3d8..8456f92 100644
--- a/asl/meta_tests.cpp
+++ b/asl/meta_tests.cpp
@@ -45,22 +45,22 @@ static_assert(!asl::trivially_move_constructible<NonMoveConstructible>);
static_assert(asl::copy_assignable<int>);
static_assert(asl::copy_assignable<CopyAssignable>);
static_assert(asl::copy_assignable<TriviallyCopyAssignable>);
-static_assert(!asl::copy_assignable<NoCopyAssignable>);
+static_assert(!asl::copy_assignable<NonCopyAssignable>);
static_assert(asl::trivially_copy_assignable<int>);
static_assert(!asl::trivially_copy_assignable<CopyAssignable>);
static_assert(asl::trivially_copy_assignable<TriviallyCopyAssignable>);
-static_assert(!asl::trivially_copy_assignable<NoCopyAssignable>);
+static_assert(!asl::trivially_copy_assignable<NonCopyAssignable>);
static_assert(asl::move_assignable<int>);
static_assert(asl::move_assignable<MoveAssignable>);
static_assert(asl::move_assignable<TriviallyMoveAssignable>);
-static_assert(!asl::move_assignable<NoMoveAssignable>);
+static_assert(!asl::move_assignable<NonMoveAssignable>);
static_assert(asl::trivially_move_assignable<int>);
static_assert(!asl::trivially_move_assignable<MoveAssignable>);
static_assert(asl::trivially_move_assignable<TriviallyMoveAssignable>);
-static_assert(!asl::trivially_move_assignable<NoMoveAssignable>);
+static_assert(!asl::trivially_move_assignable<NonMoveAssignable>);
static_assert(asl::trivially_destructible<int>);
static_assert(asl::trivially_destructible<TriviallyDestructible>);
diff --git a/asl/option.hpp b/asl/option.hpp
index 4793830..6aa5ebb 100644
--- a/asl/option.hpp
+++ b/asl/option.hpp
@@ -19,10 +19,85 @@ public:
constexpr option() = default;
constexpr option(nullopt_t) {} // NOLINT(*-explicit-conversions)
+ constexpr option(const option& other) requires copy_constructible<T>
+ {
+ if (other.m_has_value)
+ {
+ m_payload.init_unsafe(other.m_payload.as_init_unsafe());
+ m_has_value = true;
+ }
+ }
+
+ constexpr option(option&& other) requires move_constructible<T>
+ {
+ if (other.m_has_value)
+ {
+ m_payload.init_unsafe(ASL_MOVE(other.m_payload.as_init_unsafe()));
+ m_has_value = true;
+ }
+ }
+
+ constexpr option& operator=(const option& other) & requires copy_assignable<T> && copy_constructible<T>
+ {
+ if (&other == this) { return *this; }
+
+ if (other.m_has_value)
+ {
+ if (m_has_value)
+ {
+ m_payload.as_init_unsafe() = other.m_payload.as_init_unsafe();
+ }
+ else
+ {
+ m_payload.init_unsafe(other.m_payload.as_init_unsafe());
+ m_has_value = true;
+ }
+ }
+ else if (m_has_value)
+ {
+ reset();
+ }
+
+ return *this;
+ }
+
+ constexpr option& operator=(option&& other) & requires move_assignable<T> && move_constructible<T>
+ {
+ if (&other == this) { return *this; }
+
+ if (other.m_has_value)
+ {
+ if (m_has_value)
+ {
+ m_payload.as_init_unsafe() = ASL_MOVE(other.m_payload.as_init_unsafe());
+ }
+ else
+ {
+ m_payload.init_unsafe(ASL_MOVE(other.m_payload.as_init_unsafe()));
+ m_has_value = true;
+ }
+ }
+ else if (m_has_value)
+ {
+ reset();
+ }
+
+ return *this;
+ }
+
constexpr ~option() = default;
constexpr ~option() requires (!trivially_destructible<T>)
{
- if (m_has_value) { m_payload.uninit_unsafe(); }
+ reset();
+ }
+
+ constexpr void reset()
+ {
+ if (m_has_value)
+ {
+ m_payload.uninit_unsafe();
+ m_has_value = false;
+ }
}
};
diff --git a/asl/option_tests.cpp b/asl/option_tests.cpp
index ff63e1a..38bce2e 100644
--- a/asl/option_tests.cpp
+++ b/asl/option_tests.cpp
@@ -4,9 +4,31 @@
static_assert(asl::trivially_destructible<asl::option<TriviallyDestructible>>);
static_assert(!asl::trivially_destructible<asl::option<HasDestructor>>);
+static_assert(asl::copy_constructible<asl::option<int>>);
+static_assert(asl::copy_constructible<asl::option<CopyConstructible>>);
+static_assert(!asl::copy_constructible<asl::option<MoveConstructible>>);
+static_assert(!asl::copy_constructible<asl::option<NonMoveConstructible>>);
+
+static_assert(asl::move_constructible<asl::option<int>>);
+static_assert(asl::move_constructible<asl::option<CopyConstructible>>);
+static_assert(asl::move_constructible<asl::option<MoveConstructible>>);
+static_assert(!asl::move_constructible<asl::option<NonMoveConstructible>>);
+
+static_assert(asl::copy_assignable<asl::option<int>>);
+static_assert(asl::copy_assignable<asl::option<CopyAssignable>>);
+static_assert(!asl::copy_assignable<asl::option<MoveAssignable>>);
+static_assert(!asl::copy_assignable<asl::option<NonMoveAssignable>>);
+
+static_assert(asl::move_assignable<asl::option<int>>);
+static_assert(asl::move_assignable<asl::option<CopyAssignable>>);
+static_assert(!asl::move_assignable<asl::option<NonMoveAssignable>>);
+
int main()
{
- asl::option<HasDestructor> a;
- asl::option<TriviallyDestructible> b;
+ asl::option<int> a;
+ asl::option<int> b;
+
+ a = ASL_MOVE(b);
+
return 0;
}
diff --git a/asl/test_types.hpp b/asl/test_types.hpp
index a5207c6..da1faa6 100644
--- a/asl/test_types.hpp
+++ b/asl/test_types.hpp
@@ -14,11 +14,11 @@ struct NonMoveConstructible { NonMoveConstructible(NonMoveConstructible&&) = del
struct CopyAssignable { CopyAssignable& operator=(const CopyAssignable&) { return *this; } };
struct TriviallyCopyAssignable { TriviallyCopyAssignable& operator=(const TriviallyCopyAssignable&) = default; };
-struct NoCopyAssignable { NoCopyAssignable& operator=(const NoCopyAssignable&) = delete; };
+struct NonCopyAssignable { NonCopyAssignable& operator=(const NonCopyAssignable&) = delete; };
struct MoveAssignable { MoveAssignable& operator=(MoveAssignable&&) { return *this; } };
struct TriviallyMoveAssignable { TriviallyMoveAssignable& operator=(TriviallyMoveAssignable&&) = default; };
-struct NoMoveAssignable { NoMoveAssignable& operator=(NoMoveAssignable&&) = delete; };
+struct NonMoveAssignable { NonMoveAssignable& operator=(NonMoveAssignable&&) = delete; };
struct TriviallyDestructible { ~TriviallyDestructible() = default; };
struct HasDestructor { ~HasDestructor() {} };