diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:35:55 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:35:55 +0100 |
commit | 80b18cc979fcb1e772e5b7c7d45aa72602d461d7 (patch) | |
tree | 266cf3a6b23ac8f4d903a238f063b87354e231ea /asl | |
parent | 0f2d186fbd4cc637a359b1d62370174aebd2b80f (diff) |
More work on option
Diffstat (limited to 'asl')
-rw-r--r-- | asl/meta_tests.cpp | 8 | ||||
-rw-r--r-- | asl/option.hpp | 77 | ||||
-rw-r--r-- | asl/option_tests.cpp | 26 | ||||
-rw-r--r-- | asl/test_types.hpp | 4 |
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() {} };
|