From a141c401f78467bc15f62882fca5d55a007cacbb Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Mon, 17 Feb 2025 00:21:48 +0100 Subject: Reorganize everything --- asl/option.hpp | 509 --------------------------------------------------------- 1 file changed, 509 deletions(-) delete mode 100644 asl/option.hpp (limited to 'asl/option.hpp') diff --git a/asl/option.hpp b/asl/option.hpp deleted file mode 100644 index d12d4ce..0000000 --- a/asl/option.hpp +++ /dev/null @@ -1,509 +0,0 @@ -#pragma once - -#include "asl/assert.hpp" -#include "asl/meta.hpp" -#include "asl/maybe_uninit.hpp" -#include "asl/functional.hpp" -#include "asl/annotations.hpp" -#include "asl/hash.hpp" - -namespace asl -{ - -struct nullopt_t {}; -static constexpr nullopt_t nullopt{}; - -// @Todo(option) Reference -// @Todo(option) Function -// @Todo(option) Arrays - -template class option; - -namespace option_internal -{ - -template -concept not_constructible_from_option = - !constructible_from&> && - !constructible_from&> && - !constructible_from&&> && - !constructible_from&&>; - -template -concept not_assignable_from_option = - !assignable_from&> && - !assignable_from&> && - !assignable_from&&> && - !assignable_from&&>; - -template -concept not_constructible_assignable_from_option = - not_constructible_from_option && - not_assignable_from_option; - -} // namespace option_internal - -template -concept is_option = requires -{ - typename T::type; - requires same_as, option>; -}; - -template -class option -{ - static constexpr bool kHasNiche = has_niche; - - using HasValueMarker = select_t; - - maybe_uninit m_payload{}; - ASL_NO_UNIQUE_ADDRESS HasValueMarker m_has_value{}; - - template - friend class option; - - template - constexpr void construct(Args&&... args) - { - ASL_ASSERT(!has_value()); - - if constexpr (!kHasNiche) - { - m_payload.construct_unsafe(ASL_FWD(args)...); - m_has_value = true; - } - else - { - if constexpr (move_assignable) - { - m_payload.assign_unsafe(ASL_MOVE(T{ASL_FWD(args)...})); - } - else - { - m_payload.destroy_unsafe(); - m_payload.construct_unsafe(ASL_FWD(args)...); - } - } - } - - template - constexpr void assign(U&& arg) - { - ASL_ASSERT(has_value()); - m_payload.assign_unsafe(ASL_FWD(arg)); - } - -public: - using type = T; - - constexpr option() : option{nullopt} {} - - // NOLINTNEXTLINE(*-explicit-conversions) - constexpr option(nullopt_t) requires (!kHasNiche) {} - - // NOLINTNEXTLINE(*-explicit-conversions) - constexpr option(nullopt_t) requires kHasNiche : m_payload{in_place, niche_t{}} {} - - template - constexpr explicit (!convertible_from) - option(U&& value) - requires ( - kHasNiche && - constructible_from && - !same_as, option> - ) - : m_payload{in_place, ASL_FWD(value)} - {} - - template - constexpr explicit (!convertible_from) - option(U&& value) - requires ( - !kHasNiche && - constructible_from && - !is_option - ) - : m_payload{in_place, ASL_FWD(value)} - , m_has_value{true} - {} - - constexpr option(const option& other) requires trivially_copy_constructible = default; - constexpr option(const option& other) requires (!copy_constructible) = delete; - - constexpr option(const option& other) - requires copy_constructible && (!trivially_copy_constructible) - : option{nullopt} - { - if (other.has_value()) - { - construct(other.m_payload.as_init_unsafe()); - } - } - - constexpr option(option&& other) requires trivially_move_constructible = default; - constexpr option(option&& other) requires (!move_constructible) = delete; - - constexpr option(option&& other) - requires move_constructible && (!trivially_move_constructible) - : option{nullopt} - { - if (other.has_value()) - { - construct(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - } - - template - constexpr explicit (!convertible_from) - option(const option& other) - requires ( - constructible_from && - option_internal::not_constructible_from_option - ) - : option{nullopt} - { - if (other.has_value()) - { - construct(other.m_payload.as_init_unsafe()); - } - } - - template - constexpr explicit (!convertible_from) - option(option&& other) - requires ( - constructible_from && - option_internal::not_constructible_from_option - ) - : option{nullopt} - { - if (other.has_value()) - { - construct(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - } - - constexpr option& operator=(nullopt_t) & - { - reset(); - return *this; - } - - template - constexpr option& operator=(U&& value) & - requires ( - assignable_from && - constructible_from && - !is_option - ) - { - if (has_value()) - { - assign(ASL_FWD(value)); - } - else - { - construct(ASL_FWD(value)); - } - - return *this; - } - - constexpr option& operator=(const option& other) & - requires (!copy_assignable) = delete; - - constexpr option& operator=(const option& other) & - requires trivially_copy_assignable = default; - - constexpr option& operator=(const option& other) & - requires copy_assignable && (!trivially_copy_constructible) - { - if (&other == this) { return *this; } - - if (other.has_value()) - { - if (has_value()) - { - assign(other.m_payload.as_init_unsafe()); - } - else - { - construct(other.m_payload.as_init_unsafe()); - } - } - else if (has_value()) - { - reset(); - } - - return *this; - } - - constexpr option& operator=(option&& other) & - requires (!move_assignable) = delete; - - constexpr option& operator=(option&& other) & - requires trivially_move_assignable = default; - - constexpr option& operator=(option&& other) & - requires move_assignable && (!trivially_move_constructible) - { - if (&other == this) { return *this; } - - if (other.has_value()) - { - if (has_value()) - { - assign(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - else - { - construct(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - } - else if (has_value()) - { - reset(); - } - - return *this; - } - - template - constexpr option& operator=(const option& other) & - requires ( - constructible_from && - assignable_from && - option_internal::not_constructible_assignable_from_option - ) - { - if (other.has_value()) - { - if (has_value()) - { - assign(other.m_payload.as_init_unsafe()); - } - else - { - construct(other.m_payload.as_init_unsafe()); - } - } - else if (has_value()) - { - reset(); - } - - return *this; - } - - template - constexpr option& operator=(option&& other) & - requires ( - constructible_from && - assignable_from && - option_internal::not_constructible_assignable_from_option - ) - { - if (other.has_value()) - { - if (has_value()) - { - assign(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - else - { - construct(ASL_MOVE(other.m_payload.as_init_unsafe())); - } - } - else if (has_value()) - { - reset(); - } - - return *this; - } - - constexpr ~option() requires trivially_destructible = default; - constexpr ~option() requires (!trivially_destructible) - { - reset(); - } - - constexpr void reset() - { - if (!has_value()) { return; } - - if constexpr (kHasNiche) - { - if constexpr (move_assignable) - { - m_payload.assign_unsafe(ASL_MOVE(T{niche_t{}})); - } - else - { - m_payload.destroy_unsafe(); - m_payload.construct_unsafe(niche_t{}); - } - } - else - { - m_has_value = false; - m_payload.destroy_unsafe(); - } - } - - constexpr bool has_value() const - { - if constexpr (kHasNiche) - { - return m_payload.as_init_unsafe() != niche_t{}; - } - else - { - return m_has_value; - } - } - - // @Todo(C++23) Deducing this - constexpr T&& value() && - { - ASL_ASSERT_RELEASE(has_value()); - return ASL_MOVE(m_payload).as_init_unsafe(); - } - - constexpr T& value() & - { - ASL_ASSERT_RELEASE(has_value()); - return m_payload.as_init_unsafe(); - } - - constexpr const T& value() const& - { - ASL_ASSERT_RELEASE(has_value()); - return m_payload.as_init_unsafe(); - } - - template - constexpr T value_or(U&& other_value) const& - requires copy_constructible && convertible_from - { - return has_value() ? value() : static_cast(ASL_FWD(other_value)); - } - - template - constexpr T value_or(U&& other_value) && - requires move_constructible && convertible_from - { - return has_value() ? ASL_MOVE(value()) : static_cast(ASL_FWD(other_value)); - } - - template - constexpr T& emplace(Args&&... args) & - requires constructible_from - { - if (has_value()) { reset(); } - construct(ASL_FWD(args)...); - return value(); - } - - template - constexpr auto and_then(F&& f) & - requires is_option> - { - if (has_value()) - { - return invoke(ASL_FWD(f), value()); - } - return un_cvref_t>{}; - } - - template - constexpr auto and_then(F&& f) const& - requires is_option> - { - if (has_value()) - { - return invoke(ASL_FWD(f), value()); - } - return un_cvref_t>{}; - } - - template - constexpr auto and_then(F&& f) && - requires is_option> - { - if (has_value()) - { - return invoke(ASL_FWD(f), ASL_MOVE(value())); - } - return un_cvref_t>{}; - } - - template - constexpr auto transform(F&& f) & - { - using U = un_cvref_t>; - if (has_value()) - { - return option{ invoke(ASL_FWD(f), value()) }; - } - return option{}; - } - - template - constexpr auto transform(F&& f) const& - { - using U = un_cvref_t>; - if (has_value()) - { - return option{ invoke(ASL_FWD(f), value()) }; - } - return option{}; - } - - template - constexpr auto transform(F&& f) && - { - using U = un_cvref_t>; - if (has_value()) - { - return option{ invoke(ASL_FWD(f), ASL_MOVE(value())) }; - } - return option{}; - } - - template - constexpr option or_else(F&& f) const& - requires same_as>, option> - { - return has_value() ? *this : invoke(ASL_FWD(f)); - } - - template - constexpr option or_else(F&& f) && - requires same_as>, option> - { - return has_value() ? ASL_MOVE(*this) : invoke(ASL_FWD(f)); - } - - template - requires (!uniquely_represented