1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef RUNTIME_INCLUDE_TAIHE_OPTIONAL_HPP_ 16 #define RUNTIME_INCLUDE_TAIHE_OPTIONAL_HPP_ 17 // NOLINTBEGIN 18 19 #include <taihe/optional.abi.h> 20 #include <taihe/common.hpp> 21 22 #include <cstddef> 23 #include <cstdlib> 24 #include <memory> 25 #include <optional> 26 #include <stdexcept> 27 #include <utility> 28 29 namespace taihe { 30 template <typename cpp_owner_t> 31 struct optional_view; 32 33 template <typename cpp_owner_t> 34 struct optional; 35 36 template <typename cpp_owner_t> 37 struct optional_view { optional_viewtaihe::optional_view38 optional_view(cpp_owner_t *handle) noexcept : m_handle(handle) {} // main constructor 39 optional_viewtaihe::optional_view40 optional_view() noexcept : optional_view(nullptr) {} 41 optional_viewtaihe::optional_view42 optional_view(std::nullopt_t) : optional_view(nullptr) {} 43 operator booltaihe::optional_view44 explicit operator bool() const 45 { 46 return m_handle; 47 } 48 has_valuetaihe::optional_view49 bool has_value() const 50 { 51 return m_handle; 52 } 53 operator ->taihe::optional_view54 cpp_owner_t const *operator->() const 55 { 56 return m_handle; 57 } 58 operator *taihe::optional_view59 cpp_owner_t const &operator*() const 60 { 61 return *m_handle; 62 } 63 valuetaihe::optional_view64 cpp_owner_t const &value() const 65 { 66 return *m_handle; 67 } 68 value_ortaihe::optional_view69 cpp_owner_t value_or(cpp_owner_t &&default_value) const 70 { 71 if (m_handle) { 72 return *m_handle; 73 } else { 74 return std::move(default_value); 75 } 76 } 77 operator ==(optional_view const & lhs,optional_view const & rhs)78 friend bool operator==(optional_view const &lhs, optional_view const &rhs) 79 { 80 return (!lhs && !rhs) || (lhs && rhs && *lhs == *rhs); 81 } 82 operator !=(optional_view const & lhs,optional_view const & rhs)83 friend bool operator!=(optional_view const &lhs, optional_view const &rhs) 84 { 85 return !(lhs == rhs); 86 } 87 88 protected: 89 cpp_owner_t *m_handle; 90 }; 91 92 template <typename cpp_owner_t> 93 struct optional : public optional_view<cpp_owner_t> { optionaltaihe::optional94 explicit optional(cpp_owner_t *handle) noexcept : optional_view<cpp_owner_t>(handle) {} // main constructor 95 optionaltaihe::optional96 optional() noexcept : optional(nullptr) {} 97 optionaltaihe::optional98 optional(std::nullopt_t) : optional(nullptr) {} 99 100 template <typename... Args> optionaltaihe::optional101 optional(std::in_place_t, Args &&...args) : optional(new cpp_owner_t(std::forward<Args>(args)...)) 102 { 103 } 104 105 // TODO: Deprecate this 106 template <typename... Args> maketaihe::optional107 static optional make(Args &&...args) 108 { 109 return optional(std::in_place, std::forward<Args>(args)...); 110 } 111 112 template <typename... Args> emplacetaihe::optional113 cpp_owner_t &emplace(Args &&...args) 114 { 115 if (this->m_handle) { 116 delete this->m_handle; 117 } 118 this->m_handle = new cpp_owner_t(std::forward<Args>(args)...); 119 return *this->m_handle; 120 } 121 resettaihe::optional122 void reset() 123 { 124 if (this->m_handle) { 125 delete this->m_handle; 126 this->m_handle = nullptr; 127 } 128 } 129 optionaltaihe::optional130 optional(optional_view<cpp_owner_t> const &other) : optional(other ? new cpp_owner_t(*other) : nullptr) {} 131 optionaltaihe::optional132 optional(optional<cpp_owner_t> const &other) : optional(other ? new cpp_owner_t(*other) : nullptr) {} 133 optionaltaihe::optional134 optional(optional<cpp_owner_t> &&other) : optional(std::exchange(other.m_handle, nullptr)) {} 135 operator =taihe::optional136 optional &operator=(optional other) 137 { 138 std::swap(this->m_handle, other.m_handle); 139 return *this; 140 } 141 ~optionaltaihe::optional142 ~optional() 143 { 144 if (this->m_handle) { 145 delete this->m_handle; 146 } 147 } 148 }; 149 150 template <typename cpp_owner_t> 151 struct as_abi<optional_view<cpp_owner_t>> { 152 using type = struct TOptional; 153 }; 154 155 template <typename cpp_owner_t> 156 struct as_abi<optional<cpp_owner_t>> { 157 using type = struct TOptional; 158 }; 159 160 template <typename cpp_owner_t> 161 struct as_param<optional<cpp_owner_t>> { 162 using type = optional_view<cpp_owner_t>; 163 }; 164 } // namespace taihe 165 166 template <typename cpp_owner_t> 167 struct std::hash<taihe::optional<cpp_owner_t>> { operator ()std::hash168 std::size_t operator()(taihe::optional_view<cpp_owner_t> val) const 169 { 170 return val ? std::hash<cpp_owner_t>()(*val) + 0x9e3779b9 : 0; 171 } 172 }; 173 // NOLINTEND 174 #endif // RUNTIME_INCLUDE_TAIHE_OPTIONAL_HPP_