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 template<class T>
73 union trivial_helper {
74     T t;
75 };
76 
77 } // end namespace detail
78 
79 template <typename T>
80 struct is_copy_assignable {
81   template<class F>
82     static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{});
83     static std::false_type get(...);
84     static constexpr bool value = decltype(get((T*)nullptr))::value;
85 };
86 
87 template <typename T>
88 struct is_move_assignable {
89   template<class F>
90     static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{});
91     static std::false_type get(...);
92     static constexpr bool value = decltype(get((T*)nullptr))::value;
93 };
94 
95 } // end namespace llvm
96 
97 #endif // LLVM_SUPPORT_TYPE_TRAITS_H
98