LLVM  9.0.0svn
type_traits.h
Go to the documentation of this file.
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 #ifndef __has_feature
21 #define LLVM_DEFINED_HAS_FEATURE
22 #define __has_feature(x) 0
23 #endif
24 
25 namespace llvm {
26 
27 
28 /// Metafunction that determines whether the given type is either an
29 /// integral type or an enumeration type, including enum classes.
30 ///
31 /// Note that this accepts potentially more integral types than is_integral
32 /// because it is based on being implicitly convertible to an integral type.
33 /// Also note that enum classes aren't implicitly convertible to integral types,
34 /// the value may therefore need to be explicitly converted before being used.
35 template <typename T> class is_integral_or_enum {
36  using UnderlyingT = typename std::remove_reference<T>::type;
37 
38 public:
39  static const bool value =
40  !std::is_class<UnderlyingT>::value && // Filter conversion operators.
41  !std::is_pointer<UnderlyingT>::value &&
42  !std::is_floating_point<UnderlyingT>::value &&
43  (std::is_enum<UnderlyingT>::value ||
44  std::is_convertible<UnderlyingT, unsigned long long>::value);
45 };
46 
47 /// If T is a pointer, just return it. If it is not, return T&.
48 template<typename T, typename Enable = void>
50 
51 template <typename T>
53  T, typename std::enable_if<std::is_pointer<T>::value>::type> {
54  using type = T;
55 };
56 
57 /// If T is a pointer to X, return a pointer to const X. If it is not,
58 /// return const T.
59 template<typename T, typename Enable = void>
60 struct add_const_past_pointer { using type = const T; };
61 
62 template <typename T>
64  T, typename std::enable_if<std::is_pointer<T>::value>::type> {
65  using type = const typename std::remove_pointer<T>::type *;
66 };
67 
68 template <typename T, typename Enable = void>
70  using type = const T &;
71 };
72 template <typename T>
74  T, typename std::enable_if<std::is_pointer<T>::value>::type> {
76 };
77 
78 namespace detail {
79 /// Internal utility to detect trivial copy construction.
80 template<typename T> union copy_construction_triviality_helper {
81  T t;
85 };
86 /// Internal utility to detect trivial move construction.
87 template<typename T> union move_construction_triviality_helper {
88  T t;
92 };
93 
94 template<class T>
96  T t;
97 };
98 
99 } // end namespace detail
100 
101 /// An implementation of `std::is_trivially_copy_constructible` since we have
102 /// users with STLs that don't yet include it.
103 template <typename T>
105  : std::is_copy_constructible<
106  ::llvm::detail::copy_construction_triviality_helper<T>> {};
107 template <typename T>
108 struct is_trivially_copy_constructible<T &> : std::true_type {};
109 template <typename T>
110 struct is_trivially_copy_constructible<T &&> : std::false_type {};
111 
112 /// An implementation of `std::is_trivially_move_constructible` since we have
113 /// users with STLs that don't yet include it.
114 template <typename T>
116  : std::is_move_constructible<
117  ::llvm::detail::move_construction_triviality_helper<T>> {};
118 template <typename T>
119 struct is_trivially_move_constructible<T &> : std::true_type {};
120 template <typename T>
121 struct is_trivially_move_constructible<T &&> : std::true_type {};
122 
123 
124 template <typename T>
126  template<class F>
127  static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{});
128  static std::false_type get(...);
129  static constexpr bool value = decltype(get((T*)nullptr))::value;
130 };
131 
132 template <typename T>
134  template<class F>
135  static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{});
136  static std::false_type get(...);
137  static constexpr bool value = decltype(get((T*)nullptr))::value;
138 };
139 
140 
141 // An implementation of `std::is_trivially_copyable` since STL version
142 // is not equally supported by all compilers, especially GCC 4.9.
143 // Uniform implementation of this trait is important for ABI compatibility
144 // as it has an impact on SmallVector's ABI (among others).
145 template <typename T>
147 
148  // copy constructors
149  static constexpr bool has_trivial_copy_constructor =
150  std::is_copy_constructible<detail::trivial_helper<T>>::value;
151  static constexpr bool has_deleted_copy_constructor =
152  !std::is_copy_constructible<T>::value;
153 
154  // move constructors
155  static constexpr bool has_trivial_move_constructor =
156  std::is_move_constructible<detail::trivial_helper<T>>::value;
157  static constexpr bool has_deleted_move_constructor =
158  !std::is_move_constructible<T>::value;
159 
160  // copy assign
161  static constexpr bool has_trivial_copy_assign =
163  static constexpr bool has_deleted_copy_assign =
165 
166  // move assign
167  static constexpr bool has_trivial_move_assign =
169  static constexpr bool has_deleted_move_assign =
171 
172  // destructor
173  static constexpr bool has_trivial_destructor =
174  std::is_destructible<detail::trivial_helper<T>>::value;
175 
176  public:
177 
178  static constexpr bool value =
179  has_trivial_destructor &&
180  (has_deleted_move_assign || has_trivial_move_assign) &&
181  (has_deleted_move_constructor || has_trivial_move_constructor) &&
182  (has_deleted_copy_assign || has_trivial_copy_assign) &&
183  (has_deleted_copy_constructor || has_trivial_copy_constructor);
184 
185 #ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
186  static_assert(value == std::is_trivially_copyable<T>::value,
187  "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
188 #endif
189 };
190 template <typename T>
191 class is_trivially_copyable<T*> : public std::true_type {
192 };
193 
194 
195 } // end namespace llvm
196 
197 // If the compiler supports detecting whether a class is final, define
198 // an LLVM_IS_FINAL macro. If it cannot be defined properly, this
199 // macro will be left undefined.
200 #if __cplusplus >= 201402L || defined(_MSC_VER)
201 #define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
202 #elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
203 #define LLVM_IS_FINAL(Ty) __is_final(Ty)
204 #endif
205 
206 #ifdef LLVM_DEFINED_HAS_FEATURE
207 #undef __has_feature
208 #endif
209 
210 #endif // LLVM_SUPPORT_TYPE_TRAITS_H
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static const bool value
Definition: type_traits.h:39
F(f)
Definition: BitVector.h:937
Metafunction that determines whether the given type is either an integral type or an enumeration type...
Definition: type_traits.h:35
An implementation of std::is_trivially_move_constructible since we have users with STLs that don&#39;t ye...
Definition: type_traits.h:115
An implementation of std::is_trivially_copy_constructible since we have users with STLs that don&#39;t ye...
Definition: type_traits.h:104
If T is a pointer to X, return a pointer to const X.
Definition: type_traits.h:60
Internal utility to detect trivial copy construction.
Definition: type_traits.h:80
If T is a pointer, just return it. If it is not, return T&.
Definition: type_traits.h:49
Internal utility to detect trivial move construction.
Definition: type_traits.h:87