1 /* 2 * Copyright (c) 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 CPP_ABCKIT_BASE_CONCEPTS_H 17 #define CPP_ABCKIT_BASE_CONCEPTS_H 18 19 #include <type_traits> 20 21 namespace abckit::traits { 22 23 #ifdef _MSC_VER 24 #define ABCKIT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] 25 #else 26 #define ABCKIT_NO_UNIQUE_ADDRESS [[no_unique_address]] 27 #endif // _MSC_VER 28 29 /** 30 * @brief Lightweight checker that ensures core<->target API conversion validity 31 * It is designed to be empty class type. 32 * In case of inheritance the empty base optimization will be applied 33 * (see https://en.cppreference.com/w/cpp/language/ebo for the details) 34 * In case of non-static member, it should be combined with ABCKIT_NO_UNIQUE_ADDRESS attribute 35 * @tparam TargetT - View class for a target specialized C API (not core) 36 */ 37 template <class TargetT> 38 class TargetCheckCast { 39 private: 40 /** 41 * @brief Provides compile-time static contract checks 42 */ 43 static void ConceptChecks(); 44 45 /** 46 * @brief Checks that T::TargetCast() method is defined using 47 * pre-C++20 concept idiom with SFINAE and decltype to check type expression valideness 48 * @tparam T - type that is inspected againts the contract 49 * @note A general case to be matched (to false) if more specialized case fail 50 */ 51 template <typename T, typename = void> 52 struct HasTargetCastMethod : public std::false_type { 53 }; 54 55 /** 56 * @brief Checks that T::TargetCast() method is defined using 57 * pre-C++20 concept idiom with SFINAE and decltype to check type expression valideness 58 * @tparam T - type that is inspected againts the contract 59 * @note A more specialized case to be matched (to true) if the type expression below is valid for type T 60 */ 61 template <typename T> 62 struct HasTargetCastMethod<T, std::void_t<decltype(std::declval<const T &>().TargetCast())>> 63 : public std::true_type { 64 }; 65 66 template <typename T, typename = void> 67 struct HasCoreViewT : public std::false_type { 68 }; 69 70 template <typename T> 71 struct HasCoreViewT<T, std::void_t<typename T::CoreViewT>> : public std::true_type { 72 }; 73 74 public: 75 /** 76 * @brief Checking constructor, performs runtime check for target cast validity 77 * @note requires access to TargetT::TargetCast, provide such visibility at TargetT class 78 */ 79 explicit TargetCheckCast() 80 { 81 [[maybe_unused]] auto ret = static_cast<const TargetT *>(this)->TargetCast(); 82 }; 83 84 /** 85 * @brief Checking constructor, performs runtime check for target cast validity 86 * use like `explicit TagetT::TargetT(const CoreT& core) : CoreT(core), typeChecker(this) { }` 87 * @param that - Target APP view pointer that will be target checked 88 * @note requires access to TargetT::TargetCast, provide such visibility at TargetT class 89 */ 90 explicit TargetCheckCast(const TargetT *that) 91 { 92 [[maybe_unused]] auto ret = that->TargetCast(); 93 }; 94 95 /** 96 * @brief No restrictions on destuctor 97 */ 98 ~TargetCheckCast() = default; 99 100 /** 101 * @brief No restrictions on copy constructor 102 */ 103 TargetCheckCast(const TargetCheckCast &) = default; 104 105 /** 106 * @brief No restrictions on move constructor 107 */ 108 TargetCheckCast(TargetCheckCast &&) = default; 109 110 /** 111 * @brief No restrictions on copy assignment constructor 112 * @return this `TargetCheckCast` -- default chaining idiom 113 */ 114 TargetCheckCast &operator=(const TargetCheckCast &) = default; 115 116 /** 117 * @brief No restrictions on move assignment constructor 118 * @return this `TargetCheckCast` -- default chaining idiom 119 */ 120 TargetCheckCast &operator=(TargetCheckCast &&) = default; 121 }; 122 123 /** 124 * @brief Checking constructor, performs runtime check for target cast validity 125 * @tparam TargetT - View class for a target specialized C API 126 * @note requires access to TargetT::TargetCast, provide such visibility at TargetT class 127 */ 128 template <class TargetT> 129 inline void TargetCheckCast<TargetT>::ConceptChecks() 130 { 131 static_assert(sizeof(TargetCheckCast) == 0, "Concept check should not affect class layout"); 132 static_assert(HasTargetCastMethod<TargetT>::value, "Define `TargetT::TargetCast() const` returning C API pointer"); 133 static_assert(HasCoreViewT<TargetT>::value, "Define `TargetT::CoreViewT` type referring base class"); 134 static_assert(sizeof(TargetT) == sizeof(typename TargetT::CoreViewT), 135 "Target View should have the same layout as Core"); 136 } 137 138 } // namespace abckit::traits 139 140 #endif // CPP_ABCKIT_BASE_CONCEPTS_H 141