• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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