diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-07-02 17:42:50 +0200 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-07-04 07:24:41 +0430 |
commit | 515e2d9734b9d6f3a1c8e5b2764662b39cef97ce (patch) | |
tree | 2c527458ffd0e5a99cedc557e4d2759ef72bd0cc /AK/Optional.h | |
parent | 6c0b9919cee5c385e2aa7429f2c815218c1be6a6 (diff) | |
download | serenity-515e2d9734b9d6f3a1c8e5b2764662b39cef97ce.zip |
AK: Use conditionally trivial special member functions
This commit makes use of the conditionally trivial special member
functions introduced in C++20. Basically, `Optional` and `Variant`
inherits whether its wrapped type is trivially copy constructible,
trivially copy assignable or trivially destructible. This lets the
compiler optimize optimize a large number of their use cases.
The constraints have been applied to `Optional`'s converting
constructors too in order to make the API more explicit.
This feature is not supported by Clang yet, so we use conditional
compilation so that Lagom can be built on macOS. Once Clang has P0848R3
support, these can be removed.
Diffstat (limited to 'AK/Optional.h')
-rw-r--r-- | AK/Optional.h | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/AK/Optional.h b/AK/Optional.h index 7348fe9a78..54067eb5b7 100644 --- a/AK/Optional.h +++ b/AK/Optional.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -20,63 +21,56 @@ public: ALWAYS_INLINE Optional() = default; - ALWAYS_INLINE Optional(const T& value) - : m_has_value(true) - { - new (&m_storage) T(value); - } +#ifdef AK_HAS_CONDITIONALLY_TRIVIAL + Optional(const Optional& other) requires(!IsCopyConstructible<T>) = delete; + Optional(const Optional& other) = default; - template<typename U> - ALWAYS_INLINE Optional(const U& value) - : m_has_value(true) - { - new (&m_storage) T(value); - } + Optional(Optional&& other) requires(!IsMoveConstructible<T>) = delete; - ALWAYS_INLINE Optional(T&& value) - : m_has_value(true) - { - new (&m_storage) T(move(value)); - } + Optional& operator=(const Optional&) requires(!IsCopyConstructible<T> || !IsDestructible<T>) = delete; + Optional& operator=(const Optional&) = default; - ALWAYS_INLINE Optional(Optional&& other) - : m_has_value(other.m_has_value) - { - if (other.has_value()) { - new (&m_storage) T(other.release_value()); - other.m_has_value = false; - } - } + Optional& operator=(Optional&& other) requires(!IsMoveConstructible<T> || !IsDestructible<T>) = delete; + + ~Optional() requires(!IsDestructible<T>) = delete; + ~Optional() = default; +#endif ALWAYS_INLINE Optional(const Optional& other) +#ifdef AK_HAS_CONDITIONALLY_TRIVIAL + requires(!IsTriviallyCopyConstructible<T>) +#endif : m_has_value(other.m_has_value) { - if (m_has_value) { + if (other.has_value()) { new (&m_storage) T(other.value()); } } - ALWAYS_INLINE Optional(Optional& other) + ALWAYS_INLINE Optional(Optional&& other) : m_has_value(other.m_has_value) { - if (m_has_value) { - new (&m_storage) T(other.value()); + if (other.has_value()) { + new (&m_storage) T(other.release_value()); } } - template<typename U> - ALWAYS_INLINE Optional(U& value) + template<typename U = T> + ALWAYS_INLINE explicit(!IsConvertible<U&&, T>) Optional(U&& value) requires(!IsSame<RemoveCVReference<U>, Optional<T>> && IsConstructible<T, U&&>) : m_has_value(true) { - new (&m_storage) T(value); + new (&m_storage) T(forward<U>(value)); } ALWAYS_INLINE Optional& operator=(const Optional& other) +#ifdef AK_HAS_CONDITIONALLY_TRIVIAL + requires(!IsTriviallyCopyConstructible<T> || !IsTriviallyDestructible<T>) +#endif { if (this != &other) { clear(); m_has_value = other.m_has_value; - if (m_has_value) { + if (other.has_value()) { new (&m_storage) T(other.value()); } } @@ -88,8 +82,9 @@ public: if (this != &other) { clear(); m_has_value = other.m_has_value; - if (other.has_value()) + if (other.has_value()) { new (&m_storage) T(other.release_value()); + } } return *this; } @@ -107,6 +102,9 @@ public: } ALWAYS_INLINE ~Optional() +#ifdef AK_HAS_CONDITIONALLY_TRIVIAL + requires(!IsTriviallyDestructible<T>) +#endif { clear(); } @@ -167,7 +165,6 @@ private: alignas(T) u8 m_storage[sizeof(T)]; bool m_has_value { false }; }; - } using AK::Optional; |