1 /** 2 * Copyright (c) 2021-2022 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_STRUCT_FIELD_H__ 17 #define PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__ 18 19 #include "macros.h" 20 21 #include <functional> 22 // included for nullopt_t 23 #include <optional> 24 25 namespace panda::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) : 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 HasRefOptionalConstRef43 bool HasRef() const 44 { 45 return value != nullptr; 46 } 47 GetOptionalConstRef48 const T &Get() const 49 { 50 ASSERT(HasRef()); 51 return *value; 52 } 53 54 const T &operator*() const 55 { 56 return Get(); 57 } 58 AsPointerOptionalConstRef59 const T *AsPointer() const 60 { 61 return &Get(); 62 } 63 64 const T *operator->() const 65 { 66 return AsPointer(); 67 } 68 AsWrapperOptionalConstRef69 std::reference_wrapper<const T> AsWrapper() const 70 { 71 return Get(); 72 } 73 74 /** 75 * @brief The unsafe direction of const_cast, though without UB. Try to avoid using. 76 */ UnconstOptionalConstRef77 OptionalRef<T> Unconst() const 78 { 79 return OptionalRef<T> {value}; 80 } 81 82 DEFAULT_COPY_SEMANTIC(OptionalConstRef); 83 DEFAULT_MOVE_SEMANTIC(OptionalConstRef); 84 85 protected: OptionalConstRefOptionalConstRef86 explicit OptionalConstRef(T *ptr) : value {ptr} {} 87 // not const to let OptionalRef inherit this without unsafe behavior 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 GetOptionalRef110 T &Get() 111 { 112 ASSERT(OptionalConstRef<T>::HasRef()); 113 return *OptionalConstRef<T>::value; 114 } 115 116 T &operator*() 117 { 118 return Get(); 119 } 120 AsPointerOptionalRef121 T *AsPointer() 122 { 123 return &Get(); 124 } 125 126 T *operator->() 127 { 128 return AsPointer(); 129 } 130 AsWrapperOptionalRef131 std::reference_wrapper<T> AsWrapper() 132 { 133 return Get(); 134 } 135 136 DEFAULT_COPY_SEMANTIC(OptionalRef); 137 DEFAULT_MOVE_SEMANTIC(OptionalRef); 138 139 private: 140 // makes the inherited protected constructor public 141 friend struct OptionalConstRef<T>; 142 }; 143 144 } // namespace panda::verifier 145 146 #endif // !PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__ 147