1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_CPPGC_TYPE_TRAITS_H_ 6 #define INCLUDE_CPPGC_TYPE_TRAITS_H_ 7 8 // This file should stay with minimal dependencies to allow embedder to check 9 // against Oilpan types without including any other parts. 10 #include <cstddef> 11 #include <type_traits> 12 13 namespace cppgc { 14 15 class Visitor; 16 17 namespace internal { 18 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy, 19 typename CheckingPolicy> 20 class BasicMember; 21 struct DijkstraWriteBarrierPolicy; 22 struct NoWriteBarrierPolicy; 23 class StrongMemberTag; 24 class UntracedMemberTag; 25 class WeakMemberTag; 26 27 // Not supposed to be specialized by the user. 28 template <typename T> 29 struct IsWeak : std::false_type {}; 30 31 // IsTraceMethodConst is used to verify that all Trace methods are marked as 32 // const. It is equivalent to IsTraceable but for a non-const object. 33 template <typename T, typename = void> 34 struct IsTraceMethodConst : std::false_type {}; 35 36 template <typename T> 37 struct IsTraceMethodConst<T, std::void_t<decltype(std::declval<const T>().Trace( 38 std::declval<Visitor*>()))>> : std::true_type { 39 }; 40 41 template <typename T, typename = void> 42 struct IsTraceable : std::false_type { 43 static_assert(sizeof(T), "T must be fully defined"); 44 }; 45 46 template <typename T> 47 struct IsTraceable< 48 T, std::void_t<decltype(std::declval<T>().Trace(std::declval<Visitor*>()))>> 49 : std::true_type { 50 // All Trace methods should be marked as const. If an object of type 51 // 'T' is traceable then any object of type 'const T' should also 52 // be traceable. 53 static_assert(IsTraceMethodConst<T>(), 54 "Trace methods should be marked as const."); 55 }; 56 57 template <typename T> 58 constexpr bool IsTraceableV = IsTraceable<T>::value; 59 60 template <typename T, typename = void> 61 struct HasGarbageCollectedMixinTypeMarker : std::false_type { 62 static_assert(sizeof(T), "T must be fully defined"); 63 }; 64 65 template <typename T> 66 struct HasGarbageCollectedMixinTypeMarker< 67 T, std::void_t< 68 typename std::remove_const_t<T>::IsGarbageCollectedMixinTypeMarker>> 69 : std::true_type { 70 static_assert(sizeof(T), "T must be fully defined"); 71 }; 72 73 template <typename T, typename = void> 74 struct HasGarbageCollectedTypeMarker : std::false_type { 75 static_assert(sizeof(T), "T must be fully defined"); 76 }; 77 78 template <typename T> 79 struct HasGarbageCollectedTypeMarker< 80 T, 81 std::void_t<typename std::remove_const_t<T>::IsGarbageCollectedTypeMarker>> 82 : std::true_type { 83 static_assert(sizeof(T), "T must be fully defined"); 84 }; 85 86 template <typename T, bool = HasGarbageCollectedTypeMarker<T>::value, 87 bool = HasGarbageCollectedMixinTypeMarker<T>::value> 88 struct IsGarbageCollectedMixinType : std::false_type { 89 static_assert(sizeof(T), "T must be fully defined"); 90 }; 91 92 template <typename T> 93 struct IsGarbageCollectedMixinType<T, false, true> : std::true_type { 94 static_assert(sizeof(T), "T must be fully defined"); 95 }; 96 97 template <typename T, bool = HasGarbageCollectedTypeMarker<T>::value> 98 struct IsGarbageCollectedType : std::false_type { 99 static_assert(sizeof(T), "T must be fully defined"); 100 }; 101 102 template <typename T> 103 struct IsGarbageCollectedType<T, true> : std::true_type { 104 static_assert(sizeof(T), "T must be fully defined"); 105 }; 106 107 template <typename T> 108 struct IsGarbageCollectedOrMixinType 109 : std::integral_constant<bool, IsGarbageCollectedType<T>::value || 110 IsGarbageCollectedMixinType<T>::value> { 111 static_assert(sizeof(T), "T must be fully defined"); 112 }; 113 114 template <typename T, bool = (HasGarbageCollectedTypeMarker<T>::value && 115 HasGarbageCollectedMixinTypeMarker<T>::value)> 116 struct IsGarbageCollectedWithMixinType : std::false_type { 117 static_assert(sizeof(T), "T must be fully defined"); 118 }; 119 120 template <typename T> 121 struct IsGarbageCollectedWithMixinType<T, true> : std::true_type { 122 static_assert(sizeof(T), "T must be fully defined"); 123 }; 124 125 template <typename BasicMemberCandidate, typename WeaknessTag, 126 typename WriteBarrierPolicy> 127 struct IsSubclassOfBasicMemberTemplate { 128 private: 129 template <typename T, typename CheckingPolicy> 130 static std::true_type SubclassCheck( 131 BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy>*); 132 static std::false_type SubclassCheck(...); 133 134 public: 135 static constexpr bool value = 136 decltype(SubclassCheck(std::declval<BasicMemberCandidate*>()))::value; 137 }; 138 139 template <typename T, 140 bool = IsSubclassOfBasicMemberTemplate< 141 T, StrongMemberTag, DijkstraWriteBarrierPolicy>::value> 142 struct IsMemberType : std::false_type {}; 143 144 template <typename T> 145 struct IsMemberType<T, true> : std::true_type {}; 146 147 template <typename T, bool = IsSubclassOfBasicMemberTemplate< 148 T, WeakMemberTag, DijkstraWriteBarrierPolicy>::value> 149 struct IsWeakMemberType : std::false_type {}; 150 151 template <typename T> 152 struct IsWeakMemberType<T, true> : std::true_type {}; 153 154 template <typename T, bool = IsSubclassOfBasicMemberTemplate< 155 T, UntracedMemberTag, NoWriteBarrierPolicy>::value> 156 struct IsUntracedMemberType : std::false_type {}; 157 158 template <typename T> 159 struct IsUntracedMemberType<T, true> : std::true_type {}; 160 161 template <typename T> 162 struct IsComplete { 163 private: 164 template <typename U, size_t = sizeof(U)> 165 static std::true_type IsSizeOfKnown(U*); 166 static std::false_type IsSizeOfKnown(...); 167 168 public: 169 static constexpr bool value = 170 decltype(IsSizeOfKnown(std::declval<T*>()))::value; 171 }; 172 173 } // namespace internal 174 175 /** 176 * Value is true for types that inherit from `GarbageCollectedMixin` but not 177 * `GarbageCollected<T>` (i.e., they are free mixins), and false otherwise. 178 */ 179 template <typename T> 180 constexpr bool IsGarbageCollectedMixinTypeV = 181 internal::IsGarbageCollectedMixinType<T>::value; 182 183 /** 184 * Value is true for types that inherit from `GarbageCollected<T>`, and false 185 * otherwise. 186 */ 187 template <typename T> 188 constexpr bool IsGarbageCollectedTypeV = 189 internal::IsGarbageCollectedType<T>::value; 190 191 /** 192 * Value is true for types that inherit from either `GarbageCollected<T>` or 193 * `GarbageCollectedMixin`, and false otherwise. 194 */ 195 template <typename T> 196 constexpr bool IsGarbageCollectedOrMixinTypeV = 197 internal::IsGarbageCollectedOrMixinType<T>::value; 198 199 /** 200 * Value is true for types that inherit from `GarbageCollected<T>` and 201 * `GarbageCollectedMixin`, and false otherwise. 202 */ 203 template <typename T> 204 constexpr bool IsGarbageCollectedWithMixinTypeV = 205 internal::IsGarbageCollectedWithMixinType<T>::value; 206 207 /** 208 * Value is true for types of type `Member<T>`, and false otherwise. 209 */ 210 template <typename T> 211 constexpr bool IsMemberTypeV = internal::IsMemberType<T>::value; 212 213 /** 214 * Value is true for types of type `UntracedMember<T>`, and false otherwise. 215 */ 216 template <typename T> 217 constexpr bool IsUntracedMemberTypeV = internal::IsUntracedMemberType<T>::value; 218 219 /** 220 * Value is true for types of type `WeakMember<T>`, and false otherwise. 221 */ 222 template <typename T> 223 constexpr bool IsWeakMemberTypeV = internal::IsWeakMemberType<T>::value; 224 225 /** 226 * Value is true for types that are considered weak references, and false 227 * otherwise. 228 */ 229 template <typename T> 230 constexpr bool IsWeakV = internal::IsWeak<T>::value; 231 232 /** 233 * Value is true for types that are complete, and false otherwise. 234 */ 235 template <typename T> 236 constexpr bool IsCompleteV = internal::IsComplete<T>::value; 237 238 } // namespace cppgc 239 240 #endif // INCLUDE_CPPGC_TYPE_TRAITS_H_ 241