diff options
author | Glen Chung <kuchung@microsoft.com> | 2023-05-26 13:33:57 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-05-26 13:36:03 (GMT) |
commit | 3381e6bd5cbfa1694f07c97a19747adda10b06f2 (patch) | |
tree | a99c177695b41b4f6576f74a7a59a7721de96687 /Utilities/cmcppdap/include/dap/optional.h | |
parent | bd58bc7817e9546cb6726a52657f54b1cde59b0c (diff) | |
parent | 1daeefc37856c209718b406dcb86d44519393dd1 (diff) | |
download | CMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.zip CMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.tar.gz CMake-3381e6bd5cbfa1694f07c97a19747adda10b06f2.tar.bz2 |
Merge branch 'upstream-cppdap' into import-cppdap
* upstream-cppdap:
cppdap 2023-05-26 (03cc1867)
Diffstat (limited to 'Utilities/cmcppdap/include/dap/optional.h')
-rw-r--r-- | Utilities/cmcppdap/include/dap/optional.h | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/Utilities/cmcppdap/include/dap/optional.h b/Utilities/cmcppdap/include/dap/optional.h new file mode 100644 index 0000000..9a3d216 --- /dev/null +++ b/Utilities/cmcppdap/include/dap/optional.h @@ -0,0 +1,263 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef dap_optional_h +#define dap_optional_h + +#include <assert.h> +#include <type_traits> +#include <utility> // std::move, std::forward + +namespace dap { + +// optional holds an 'optional' contained value. +// This is similar to C++17's std::optional. +template <typename T> +class optional { + template <typename U> + using IsConvertibleToT = + typename std::enable_if<std::is_convertible<U, T>::value>::type; + + public: + using value_type = T; + + // constructors + inline optional() = default; + inline optional(const optional& other); + inline optional(optional&& other); + template <typename U> + inline optional(const optional<U>& other); + template <typename U> + inline optional(optional<U>&& other); + template <typename U = value_type, typename = IsConvertibleToT<U>> + inline optional(U&& value); + + // value() returns the contained value. + // If the optional does not contain a value, then value() will assert. + inline T& value(); + inline const T& value() const; + + // value() returns the contained value, or defaultValue if the optional does + // not contain a value. + inline const T& value(const T& defaultValue) const; + + // operator bool() returns true if the optional contains a value. + inline explicit operator bool() const noexcept; + + // has_value() returns true if the optional contains a value. + inline bool has_value() const; + + // assignment + inline optional& operator=(const optional& other); + inline optional& operator=(optional&& other) noexcept; + template <typename U = T, typename = IsConvertibleToT<U>> + inline optional& operator=(U&& value); + template <typename U> + inline optional& operator=(const optional<U>& other); + template <typename U> + inline optional& operator=(optional<U>&& other); + + // value access + inline const T* operator->() const; + inline T* operator->(); + inline const T& operator*() const; + inline T& operator*(); + + private: + T val{}; + bool set = false; +}; + +template <typename T> +optional<T>::optional(const optional& other) : val(other.val), set(other.set) {} + +template <typename T> +optional<T>::optional(optional&& other) + : val(std::move(other.val)), set(other.set) {} + +template <typename T> +template <typename U> +optional<T>::optional(const optional<U>& other) : set(other.has_value()) { + if (set) { + val = static_cast<T>(other.value()); + } +} + +template <typename T> +template <typename U> +optional<T>::optional(optional<U>&& other) : set(other.has_value()) { + if (set) { + val = static_cast<T>(std::move(other.value())); + } +} + +template <typename T> +template <typename U /*= T*/, typename> +optional<T>::optional(U&& value) : val(std::forward<U>(value)), set(true) {} + +template <typename T> +T& optional<T>::value() { + assert(set); + return val; +} + +template <typename T> +const T& optional<T>::value() const { + assert(set); + return val; +} + +template <typename T> +const T& optional<T>::value(const T& defaultValue) const { + if (!has_value()) { + return defaultValue; + } + return val; +} + +template <typename T> +optional<T>::operator bool() const noexcept { + return set; +} + +template <typename T> +bool optional<T>::has_value() const { + return set; +} + +template <typename T> +optional<T>& optional<T>::operator=(const optional& other) { + val = other.val; + set = other.set; + return *this; +} + +template <typename T> +optional<T>& optional<T>::operator=(optional&& other) noexcept { + val = std::move(other.val); + set = other.set; + return *this; +} + +template <typename T> +template <typename U /* = T */, typename> +optional<T>& optional<T>::operator=(U&& value) { + val = std::forward<U>(value); + set = true; + return *this; +} + +template <typename T> +template <typename U> +optional<T>& optional<T>::operator=(const optional<U>& other) { + val = other.val; + set = other.set; + return *this; +} + +template <typename T> +template <typename U> +optional<T>& optional<T>::operator=(optional<U>&& other) { + val = std::move(other.val); + set = other.set; + return *this; +} + +template <typename T> +const T* optional<T>::operator->() const { + assert(set); + return &val; +} + +template <typename T> +T* optional<T>::operator->() { + assert(set); + return &val; +} + +template <typename T> +const T& optional<T>::operator*() const { + assert(set); + return val; +} + +template <typename T> +T& optional<T>::operator*() { + assert(set); + return val; +} + +template <class T, class U> +inline bool operator==(const optional<T>& lhs, const optional<U>& rhs) { + if (!lhs.has_value() && !rhs.has_value()) { + return true; + } + if (!lhs.has_value() || !rhs.has_value()) { + return false; + } + return lhs.value() == rhs.value(); +} + +template <class T, class U> +inline bool operator!=(const optional<T>& lhs, const optional<U>& rhs) { + return !(lhs == rhs); +} + +template <class T, class U> +inline bool operator<(const optional<T>& lhs, const optional<U>& rhs) { + if (!rhs.has_value()) { + return false; + } + if (!lhs.has_value()) { + return true; + } + return lhs.value() < rhs.value(); +} + +template <class T, class U> +inline bool operator<=(const optional<T>& lhs, const optional<U>& rhs) { + if (!lhs.has_value()) { + return true; + } + if (!rhs.has_value()) { + return false; + } + return lhs.value() <= rhs.value(); +} + +template <class T, class U> +inline bool operator>(const optional<T>& lhs, const optional<U>& rhs) { + if (!lhs.has_value()) { + return false; + } + if (!rhs.has_value()) { + return true; + } + return lhs.value() > rhs.value(); +} + +template <class T, class U> +inline bool operator>=(const optional<T>& lhs, const optional<U>& rhs) { + if (!rhs.has_value()) { + return true; + } + if (!lhs.has_value()) { + return false; + } + return lhs.value() >= rhs.value(); +} + +} // namespace dap + +#endif // dap_optional_h |