1 //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file provides useful additions to the standard type_traits library. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_SUPPORT_TYPE_TRAITS_H 14 #define LLVM_SUPPORT_TYPE_TRAITS_H 15 16 #include "llvm/Support/Compiler.h" 17 #include <type_traits> 18 #include <utility> 19 20 namespace llvm { 21 22 23 /// Metafunction that determines whether the given type is either an 24 /// integral type or an enumeration type, including enum classes. 25 /// 26 /// Note that this accepts potentially more integral types than is_integral 27 /// because it is based on being implicitly convertible to an integral type. 28 /// Also note that enum classes aren't implicitly convertible to integral types, 29 /// the value may therefore need to be explicitly converted before being used. 30 template <typename T> class is_integral_or_enum { 31 using UnderlyingT = std::remove_reference_t<T>; 32 33 public: 34 static const bool value = 35 !std::is_class_v<UnderlyingT> && // Filter conversion operators. 36 !std::is_pointer_v<UnderlyingT> && 37 !std::is_floating_point_v<UnderlyingT> && 38 (std::is_enum_v<UnderlyingT> || 39 std::is_convertible_v<UnderlyingT, unsigned long long>); 40 }; 41 42 /// If T is a pointer, just return it. If it is not, return T&. 43 template<typename T, typename Enable = void> 44 struct add_lvalue_reference_if_not_pointer { using type = T &; }; 45 46 template <typename T> 47 struct add_lvalue_reference_if_not_pointer< 48 T, std::enable_if_t<std::is_pointer_v<T>>> { 49 using type = T; 50 }; 51 52 /// If T is a pointer to X, return a pointer to const X. If it is not, 53 /// return const T. 54 template<typename T, typename Enable = void> 55 struct add_const_past_pointer { using type = const T; }; 56 57 template <typename T> 58 struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer_v<T>>> { 59 using type = const std::remove_pointer_t<T> *; 60 }; 61 62 template <typename T, typename Enable = void> 63 struct const_pointer_or_const_ref { 64 using type = const T &; 65 }; 66 template <typename T> 67 struct const_pointer_or_const_ref<T, std::enable_if_t<std::is_pointer_v<T>>> { 68 using type = typename add_const_past_pointer<T>::type; 69 }; 70 71 namespace detail { 72 /// Internal utility to detect trivial copy construction. 73 template<typename T> union copy_construction_triviality_helper { 74 T t; 75 copy_construction_triviality_helper() = default; 76 copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default; 77 ~copy_construction_triviality_helper() = default; 78 }; 79 /// Internal utility to detect trivial move construction. 80 template<typename T> union move_construction_triviality_helper { 81 T t; 82 move_construction_triviality_helper() = default; 83 move_construction_triviality_helper(move_construction_triviality_helper&&) = default; 84 ~move_construction_triviality_helper() = default; 85 }; 86 87 template<class T> 88 union trivial_helper { 89 T t; 90 }; 91 92 } // end namespace detail 93 94 /// An implementation of `std::is_trivially_copy_constructible` since we have 95 /// users with STLs that don't yet include it. 96 template <typename T> 97 struct is_trivially_copy_constructible 98 : std::is_copy_constructible< 99 ::llvm::detail::copy_construction_triviality_helper<T>> {}; 100 template <typename T> 101 struct is_trivially_copy_constructible<T &> : std::true_type {}; 102 template <typename T> 103 struct is_trivially_copy_constructible<T &&> : std::false_type {}; 104 105 /// An implementation of `std::is_trivially_move_constructible` since we have 106 /// users with STLs that don't yet include it. 107 template <typename T> 108 struct is_trivially_move_constructible 109 : std::is_move_constructible< 110 ::llvm::detail::move_construction_triviality_helper<T>> {}; 111 template <typename T> 112 struct is_trivially_move_constructible<T &> : std::true_type {}; 113 template <typename T> 114 struct is_trivially_move_constructible<T &&> : std::true_type {}; 115 116 117 template <typename T> 118 struct is_copy_assignable { 119 template<class F> 120 static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{}); 121 static std::false_type get(...); 122 static constexpr bool value = decltype(get((T*)nullptr))::value; 123 }; 124 125 template <typename T> 126 struct is_move_assignable { 127 template<class F> 128 static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{}); 129 static std::false_type get(...); 130 static constexpr bool value = decltype(get((T*)nullptr))::value; 131 }; 132 133 } // end namespace llvm 134 135 #endif // LLVM_SUPPORT_TYPE_TRAITS_H 136