/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * 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 * * http://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 PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__ #define PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__ #include "macros.h" #include // included for nullopt_t #include namespace panda::verifier { template struct OptionalRef; template struct OptionalConstRef { public: OptionalConstRef() : value {nullptr} {} // These are intentionally implicit for consistency with std::optional // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRef(std::nullopt_t) : value {nullptr} {} // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRef(const T &reference) : value {const_cast(&reference)} {} // NOLINTNEXTLINE(google-explicit-constructor) OptionalConstRef(std::reference_wrapper reference) : OptionalConstRef(reference.get()) {} explicit OptionalConstRef(const T *ptr) : value {const_cast(ptr)} {} bool HasRef() const { return value != nullptr; } const T &Get() const { ASSERT(HasRef()); return *value; } const T &operator*() const { return Get(); } const T *AsPointer() const { return &Get(); } const T *operator->() const { return AsPointer(); } std::reference_wrapper AsWrapper() const { return Get(); } /** * @brief The unsafe direction of const_cast, though without UB. Try to avoid using. */ OptionalRef Unconst() const { return OptionalRef {value}; } DEFAULT_COPY_SEMANTIC(OptionalConstRef); DEFAULT_MOVE_SEMANTIC(OptionalConstRef); protected: explicit OptionalConstRef(T *ptr) : value {ptr} {} // not const to let OptionalRef inherit this without unsafe behavior T *value; }; /** * @brief Morally equivalent to std::optional>, but nicer to use and takes less memory * * @tparam T The referenced type */ template struct OptionalRef : public OptionalConstRef { public: using OptionalConstRef::OptionalConstRef; using OptionalConstRef::Get; using OptionalConstRef::AsPointer; using OptionalConstRef::AsWrapper; using OptionalConstRef::operator->; using OptionalConstRef::operator*; // NOLINTNEXTLINE(google-explicit-constructor) OptionalRef(T &reference) : OptionalConstRef(&reference) {} // NOLINTNEXTLINE(google-explicit-constructor) OptionalRef(std::reference_wrapper reference) : OptionalRef(reference.get()) {} T &Get() { ASSERT(OptionalConstRef::HasRef()); return *OptionalConstRef::value; } T &operator*() { return Get(); } T *AsPointer() { return &Get(); } T *operator->() { return AsPointer(); } std::reference_wrapper AsWrapper() { return Get(); } DEFAULT_COPY_SEMANTIC(OptionalRef); DEFAULT_MOVE_SEMANTIC(OptionalRef); private: // makes the inherited protected constructor public friend struct OptionalConstRef; }; } // namespace panda::verifier #endif // !PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__