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 #include <type_traits> 9 10 namespace cppgc { 11 12 class Visitor; 13 14 namespace internal { 15 16 // Pre-C++17 custom implementation of std::void_t. 17 template <typename... Ts> 18 struct make_void { 19 typedef void type; 20 }; 21 template <typename... Ts> 22 using void_t = typename make_void<Ts...>::type; 23 24 // Not supposed to be specialized by the user. 25 template <typename T> 26 struct IsWeak : std::false_type {}; 27 28 template <typename T, template <typename... V> class U> 29 struct IsSubclassOfTemplate { 30 private: 31 template <typename... W> 32 static std::true_type SubclassCheck(U<W...>*); 33 static std::false_type SubclassCheck(...); 34 35 public: 36 static constexpr bool value = 37 decltype(SubclassCheck(std::declval<T*>()))::value; 38 }; 39 40 // IsTraceMethodConst is used to verify that all Trace methods are marked as 41 // const. It is equivalent to IsTraceable but for a non-const object. 42 template <typename T, typename = void> 43 struct IsTraceMethodConst : std::false_type {}; 44 45 template <typename T> 46 struct IsTraceMethodConst<T, void_t<decltype(std::declval<const T>().Trace( 47 std::declval<Visitor*>()))>> : std::true_type { 48 }; 49 50 template <typename T, typename = void> 51 struct IsTraceable : std::false_type { 52 static_assert(sizeof(T), "T must be fully defined"); 53 }; 54 55 template <typename T> 56 struct IsTraceable< 57 T, void_t<decltype(std::declval<T>().Trace(std::declval<Visitor*>()))>> 58 : std::true_type { 59 // All Trace methods should be marked as const. If an object of type 60 // 'T' is traceable then any object of type 'const T' should also 61 // be traceable. 62 static_assert(IsTraceMethodConst<T>(), 63 "Trace methods should be marked as const."); 64 }; 65 66 template <typename T> 67 constexpr bool IsTraceableV = IsTraceable<T>::value; 68 69 template <typename T, typename = void> 70 struct IsGarbageCollectedMixinType : std::false_type { 71 static_assert(sizeof(T), "T must be fully defined"); 72 }; 73 74 template <typename T> 75 struct IsGarbageCollectedMixinType< 76 T, 77 void_t<typename std::remove_const_t<T>::IsGarbageCollectedMixinTypeMarker>> 78 : std::true_type { 79 static_assert(sizeof(T), "T must be fully defined"); 80 }; 81 82 template <typename T, typename = void> 83 struct IsGarbageCollectedType : IsGarbageCollectedMixinType<T> { 84 static_assert(sizeof(T), "T must be fully defined"); 85 }; 86 87 template <typename T> 88 struct IsGarbageCollectedType< 89 T, void_t<typename std::remove_const_t<T>::IsGarbageCollectedTypeMarker>> 90 : std::true_type { 91 static_assert(sizeof(T), "T must be fully defined"); 92 }; 93 94 template <typename T> 95 constexpr bool IsGarbageCollectedTypeV = 96 internal::IsGarbageCollectedType<T>::value; 97 98 template <typename T> 99 constexpr bool IsGarbageCollectedMixinTypeV = 100 internal::IsGarbageCollectedMixinType<T>::value; 101 102 } // namespace internal 103 104 template <typename T> 105 constexpr bool IsWeakV = internal::IsWeak<T>::value; 106 107 } // namespace cppgc 108 109 #endif // INCLUDE_CPPGC_TYPE_TRAITS_H_ 110