1 /** 2 * Copyright (c) 2021-2024 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 16 #ifndef PANDA_VERIFIER_UTIL_OPTIONAL_REF_H 17 #define PANDA_VERIFIER_UTIL_OPTIONAL_REF_H 18 19 #include "macros.h" 20 21 #include <functional> 22 // included for nullopt_t 23 #include <optional> 24 25 namespace ark::verifier { 26 27 template <typename T> 28 struct OptionalRef; 29 30 template <typename T> 31 struct OptionalConstRef { 32 public: OptionalConstRefOptionalConstRef33 OptionalConstRef() : value_ {nullptr} {} 34 // These are intentionally implicit for consistency with std::optional 35 // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRefOptionalConstRef36 OptionalConstRef(std::nullopt_t /* unused */) : value_ {nullptr} {} 37 // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRefOptionalConstRef38 OptionalConstRef(const T &reference) : value_ {const_cast<T *>(&reference)} {} 39 // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRefOptionalConstRef40 OptionalConstRef(std::reference_wrapper<const T> reference) : OptionalConstRef(reference.get()) {} OptionalConstRefOptionalConstRef41 explicit OptionalConstRef(const T *ptr) : value_ {const_cast<T *>(ptr)} {} 42 ~OptionalConstRef() = default; 43 HasRefOptionalConstRef44 bool HasRef() const 45 { 46 return value_ != nullptr; 47 } 48 GetOptionalConstRef49 const T &Get() const 50 { 51 ASSERT(HasRef()); 52 return *value_; 53 } 54 55 const T &operator*() const 56 { 57 return Get(); 58 } 59 AsPointerOptionalConstRef60 const T *AsPointer() const 61 { 62 return &Get(); 63 } 64 65 const T *operator->() const 66 { 67 return AsPointer(); 68 } 69 AsWrapperOptionalConstRef70 std::reference_wrapper<const T> AsWrapper() const 71 { 72 return Get(); 73 } 74 75 /// @brief The unsafe direction of const_cast, though without UB. Try to avoid using. UnconstOptionalConstRef76 OptionalRef<T> Unconst() const 77 { 78 return OptionalRef<T> {value_}; 79 } 80 81 DEFAULT_COPY_SEMANTIC(OptionalConstRef); 82 DEFAULT_MOVE_SEMANTIC(OptionalConstRef); 83 84 protected: OptionalConstRefOptionalConstRef85 explicit OptionalConstRef(T *ptr) : value_ {ptr} {} 86 // not const to let OptionalRef inherit this without unsafe behavior 87 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 88 T *value_; 89 }; 90 91 /** 92 * @brief Morally equivalent to std::optional<std::reference_wrapper<T>>, but nicer to use and takes less memory 93 * 94 * @tparam T The referenced type 95 */ 96 template <typename T> 97 struct OptionalRef : public OptionalConstRef<T> { 98 public: 99 using OptionalConstRef<T>::OptionalConstRef; 100 using OptionalConstRef<T>::Get; 101 using OptionalConstRef<T>::AsPointer; 102 using OptionalConstRef<T>::AsWrapper; 103 using OptionalConstRef<T>::operator->; 104 using OptionalConstRef<T>::operator*; 105 // NOLINTNEXTLINE(google-explicit-constructor) OptionalRefOptionalRef106 OptionalRef(T &reference) : OptionalConstRef<T>(&reference) {} 107 // NOLINTNEXTLINE(google-explicit-constructor) OptionalRefOptionalRef108 OptionalRef(std::reference_wrapper<T> reference) : OptionalRef(reference.get()) {} 109 ~OptionalRef() = default; 110 GetOptionalRef111 T &Get() 112 { 113 ASSERT(OptionalConstRef<T>::HasRef()); 114 return *OptionalConstRef<T>::value_; // NOLINT(clang-analyzer-core.uninitialized.UndefReturn) 115 } 116 117 T &operator*() 118 { 119 return Get(); 120 } 121 AsPointerOptionalRef122 T *AsPointer() 123 { 124 return &Get(); 125 } 126 127 T *operator->() 128 { 129 return AsPointer(); 130 } 131 AsWrapperOptionalRef132 std::reference_wrapper<T> AsWrapper() 133 { 134 return Get(); 135 } 136 137 DEFAULT_COPY_SEMANTIC(OptionalRef); 138 DEFAULT_MOVE_SEMANTIC(OptionalRef); 139 140 private: 141 // makes the inherited protected constructor public 142 friend struct OptionalConstRef<T>; 143 }; 144 145 } // namespace ark::verifier 146 147 #endif // !PANDA_VERIFIER_UTIL_OPTIONAL_REF_H 148