From 80b18cc979fcb1e772e5b7c7d45aa72602d461d7 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Fri, 20 Dec 2024 15:35:55 +0100 Subject: More work on option --- asl/meta_tests.cpp | 8 +++--- asl/option.hpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++- asl/option_tests.cpp | 26 ++++++++++++++++-- asl/test_types.hpp | 4 +-- 4 files changed, 106 insertions(+), 9 deletions(-) (limited to 'asl') 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); static_assert(asl::copy_assignable); static_assert(asl::copy_assignable); static_assert(asl::copy_assignable); -static_assert(!asl::copy_assignable); +static_assert(!asl::copy_assignable); static_assert(asl::trivially_copy_assignable); static_assert(!asl::trivially_copy_assignable); static_assert(asl::trivially_copy_assignable); -static_assert(!asl::trivially_copy_assignable); +static_assert(!asl::trivially_copy_assignable); static_assert(asl::move_assignable); static_assert(asl::move_assignable); static_assert(asl::move_assignable); -static_assert(!asl::move_assignable); +static_assert(!asl::move_assignable); static_assert(asl::trivially_move_assignable); static_assert(!asl::trivially_move_assignable); static_assert(asl::trivially_move_assignable); -static_assert(!asl::trivially_move_assignable); +static_assert(!asl::trivially_move_assignable); static_assert(asl::trivially_destructible); static_assert(asl::trivially_destructible); 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 + { + 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 + { + 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 && copy_constructible + { + 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 && move_constructible + { + 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) { - 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>); static_assert(!asl::trivially_destructible>); +static_assert(asl::copy_constructible>); +static_assert(asl::copy_constructible>); +static_assert(!asl::copy_constructible>); +static_assert(!asl::copy_constructible>); + +static_assert(asl::move_constructible>); +static_assert(asl::move_constructible>); +static_assert(asl::move_constructible>); +static_assert(!asl::move_constructible>); + +static_assert(asl::copy_assignable>); +static_assert(asl::copy_assignable>); +static_assert(!asl::copy_assignable>); +static_assert(!asl::copy_assignable>); + +static_assert(asl::move_assignable>); +static_assert(asl::move_assignable>); +static_assert(!asl::move_assignable>); + int main() { - asl::option a; - asl::option b; + asl::option a; + asl::option 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() {} }; -- cgit