| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- // 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
|