DPC++ Runtime
Runtime libraries for oneAPI DPC++
type_traits.hpp
Go to the documentation of this file.
1 //==----------------- type_traits.hpp - SYCL type traits -------------------==//
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 #pragma once
10 
11 #include <sycl/access/access.hpp> // for decorated, address_space
12 #include <sycl/detail/generic_type_lists.hpp> // for vec, marray, integer_list
13 #include <sycl/detail/type_list.hpp> // for is_contained, find_twi...
14 
15 #include <array> // for array
16 #include <cstddef> // for size_t
17 #include <tuple> // for tuple
18 #include <type_traits> // for true_type, false_type
19 
20 namespace sycl {
21 inline namespace _V1 {
22 namespace detail {
23 template <class T> struct is_fixed_size_group : std::false_type {};
24 
25 template <class T>
27 
28 template <typename VecT, typename OperationLeftT, typename OperationRightT,
29  template <typename> class OperationCurrentT, int... Indexes>
30 class SwizzleOp;
31 } // namespace detail
32 
33 template <int Dimensions> class group;
34 struct sub_group;
35 namespace ext::oneapi {
36 struct sub_group;
37 
38 namespace experimental {
39 template <typename Group, std::size_t Extent> class group_with_scratchpad;
40 
41 template <class T> struct is_fixed_topology_group : std::false_type {};
42 
43 template <class T>
44 inline constexpr bool is_fixed_topology_group_v =
46 
47 template <int Dimensions> class root_group;
48 template <int Dimensions>
49 struct is_fixed_topology_group<root_group<Dimensions>> : std::true_type {};
50 
51 template <int Dimensions>
52 struct is_fixed_topology_group<sycl::group<Dimensions>> : std::true_type {};
53 
54 template <>
55 struct is_fixed_topology_group<sycl::ext::oneapi::sub_group> : std::true_type {
56 };
57 template <> struct is_fixed_topology_group<sycl::sub_group> : std::true_type {};
58 
59 template <class T> struct is_user_constructed_group : std::false_type {};
60 
61 template <class T>
62 inline constexpr bool is_user_constructed_group_v =
64 
65 namespace detail {
66 template <typename T> struct is_group_helper : std::false_type {};
67 
68 template <typename Group, std::size_t Extent>
69 struct is_group_helper<group_with_scratchpad<Group, Extent>> : std::true_type {
70 };
71 } // namespace detail
72 } // namespace experimental
73 } // namespace ext::oneapi
74 
75 namespace detail {
76 
77 template <typename T> struct is_group : std::false_type {};
78 
79 template <int Dimensions>
80 struct is_group<group<Dimensions>> : std::true_type {};
81 
82 template <typename T> struct is_sub_group : std::false_type {};
83 
84 template <> struct is_sub_group<ext::oneapi::sub_group> : std::true_type {};
85 template <> struct is_sub_group<sycl::sub_group> : std::true_type {};
86 
87 template <typename T>
89  : std::integral_constant<bool,
90  is_group<T>::value || is_sub_group<T>::value> {};
91 template <typename T>
93 
94 namespace half_impl {
95 class half;
96 }
97 } // namespace detail
99 
100 // Forward declaration
101 template <typename ElementType, access::address_space Space,
102  access::decorated DecorateAddress>
103 class multi_ptr;
104 
105 template <class T>
106 struct is_group : std::bool_constant<detail::is_group<T>::value ||
107  detail::is_sub_group<T>::value> {};
108 
109 template <class T> inline constexpr bool is_group_v = is_group<T>::value;
110 
111 namespace ext::oneapi::experimental {
112 template <class T>
113 inline constexpr bool is_group_helper_v =
115 } // namespace ext::oneapi::experimental
116 
117 namespace detail {
118 // Type for Intel device UUID extension.
119 // For details about this extension, see
120 // sycl/doc/extensions/supported/sycl_ext_intel_device_info.md
121 using uuid_type = std::array<unsigned char, 16>;
122 
123 template <typename T, typename R> struct copy_cv_qualifiers;
124 
125 template <typename T, typename R>
127 
128 template <int V> using int_constant = std::integral_constant<int, V>;
129 // vector_size
130 // scalars are interpreted as a vector of 1 length.
131 template <typename T> struct vector_size_impl : int_constant<1> {};
132 template <typename T, int N>
133 struct vector_size_impl<vec<T, N>> : int_constant<N> {};
134 template <typename T>
136  : vector_size_impl<std::remove_cv_t<std::remove_reference_t<T>>> {};
137 
138 // vector_element
139 template <typename T> struct vector_element_impl;
140 template <typename T>
142 template <typename T> struct vector_element_impl {
143  using type = T;
144 };
145 template <typename T, int N> struct vector_element_impl<vec<T, N>> {
146  using type = T;
147 };
148 template <typename T> struct vector_element {
149  using type =
151 };
152 template <class T> using vector_element_t = typename vector_element<T>::type;
153 
154 template <class T> using marray_element_t = typename T::value_type;
155 
156 // get_elem_type
157 // Get the element type of T. If T is a scalar, the element type is considered
158 // the type of the scalar.
159 template <typename T, typename = void> struct get_elem_type {
160  using type = T;
161 };
162 template <typename T, size_t N> struct get_elem_type<marray<T, N>> {
163  using type = T;
164 };
165 template <typename T, int N> struct get_elem_type<vec<T, N>> {
166  using type = T;
167 };
168 template <typename VecT, typename OperationLeftT, typename OperationRightT,
169  template <typename> class OperationCurrentT, int... Indexes>
170 struct get_elem_type<SwizzleOp<VecT, OperationLeftT, OperationRightT,
171  OperationCurrentT, Indexes...>> {
173 };
174 
175 template <typename ElementType, access::address_space Space,
176  access::decorated DecorateAddress>
177 struct get_elem_type<multi_ptr<ElementType, Space, DecorateAddress>> {
178  using type = ElementType;
179 };
180 
181 template <typename T, typename = void>
182 struct is_ext_vector : std::false_type {};
183 
184 template <typename T>
186  T, std::void_t<decltype(__builtin_reduce_max(std::declval<T>()))>>
187  : std::true_type {};
188 
189 template <typename T>
190 inline constexpr bool is_ext_vector_v = is_ext_vector<T>::value;
191 
192 template <typename T>
193 struct get_elem_type<T, std::enable_if_t<is_ext_vector_v<T>>> {
194  using type = decltype(__builtin_reduce_max(std::declval<T>()));
195 };
196 
197 template <typename T> using get_elem_type_t = typename get_elem_type<T>::type;
198 
199 // change_base_type_t
200 template <typename T, typename B> struct change_base_type {
201  using type = B;
202 };
203 
204 template <typename T, int N, typename B> struct change_base_type<vec<T, N>, B> {
205  using type = vec<B, N>;
206 };
207 
208 template <typename T, typename B>
210 
211 // Applies the same the cv-qualifiers from T type to R type
212 template <typename T, typename R> struct copy_cv_qualifiers_impl {
213  using type = R;
214 };
215 
216 template <typename T, typename R> struct copy_cv_qualifiers_impl<const T, R> {
217  using type = const R;
218 };
219 
220 template <typename T, typename R>
221 struct copy_cv_qualifiers_impl<volatile T, R> {
222  using type = volatile R;
223 };
224 
225 template <typename T, typename R>
226 struct copy_cv_qualifiers_impl<const volatile T, R> {
227  using type = const volatile R;
228 };
229 
230 template <typename T, typename R> struct copy_cv_qualifiers {
232 };
233 
234 // make_signed with support SYCL vec class
235 template <typename T> struct make_signed {
236  using type = std::make_signed_t<T>;
237 };
238 template <typename T> using make_signed_t = typename make_signed<T>::type;
239 template <class T> struct make_signed<const T> {
240  using type = const make_signed_t<T>;
241 };
242 template <class T, int N> struct make_signed<vec<T, N>> {
244 };
245 template <typename VecT, typename OperationLeftT, typename OperationRightT,
246  template <typename> class OperationCurrentT, int... Indexes>
247 struct make_signed<SwizzleOp<VecT, OperationLeftT, OperationRightT,
248  OperationCurrentT, Indexes...>> {
250 };
251 template <class T, std::size_t N> struct make_signed<marray<T, N>> {
253 };
254 
255 // make_unsigned with support SYCL vec class
256 template <typename T> struct make_unsigned {
257  using type = std::make_unsigned_t<T>;
258 };
259 template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
260 template <class T> struct make_unsigned<const T> {
261  using type = const make_unsigned_t<T>;
262 };
263 template <class T, int N> struct make_unsigned<vec<T, N>> {
265 };
266 template <typename VecT, typename OperationLeftT, typename OperationRightT,
267  template <typename> class OperationCurrentT, int... Indexes>
268 struct make_unsigned<SwizzleOp<VecT, OperationLeftT, OperationRightT,
269  OperationCurrentT, Indexes...>> {
271 };
272 template <class T, std::size_t N> struct make_unsigned<marray<T, N>> {
274 };
275 
276 // Checks that sizeof base type of T equal N and T satisfies S<T>::value
277 template <typename T, int N, template <typename> class S>
278 inline constexpr bool is_gen_based_on_type_sizeof_v =
279  S<T>::value && (sizeof(vector_element_t<T>) == N);
280 
281 template <typename> struct is_vec : std::false_type {};
282 template <typename T, int N> struct is_vec<sycl::vec<T, N>> : std::true_type {};
283 
284 template <typename T> constexpr bool is_vec_v = is_vec<T>::value;
285 
286 template <typename> struct get_vec_size {
287  static constexpr int size = 1;
288 };
289 
290 template <typename T, int N> struct get_vec_size<sycl::vec<T, N>> {
291  static constexpr int size = N;
292 };
293 
294 // is_marray
295 template <typename> struct is_marray : std::false_type {};
296 template <typename T, size_t N>
297 struct is_marray<sycl::marray<T, N>> : std::true_type {};
298 
299 template <typename T> constexpr bool is_marray_v = is_marray<T>::value;
300 
301 // is_integral
302 template <typename T>
303 struct is_integral : std::is_integral<vector_element_t<T>> {};
304 
305 // is_floating_point
306 template <typename T>
307 struct is_floating_point_impl : std::is_floating_point<T> {};
308 
309 template <> struct is_floating_point_impl<half> : std::true_type {};
310 
311 template <typename T>
313  : is_floating_point_impl<std::remove_cv_t<vector_element_t<T>>> {};
314 
315 // is_arithmetic
316 template <typename T>
318  : std::bool_constant<is_integral<T>::value || is_floating_point<T>::value> {
319 };
320 
321 template <typename T>
323  : std::bool_constant<!is_vec<T>::value && is_arithmetic<T>::value> {};
324 
325 template <typename T>
327 
328 template <typename T>
330  : std::bool_constant<is_vec<T>::value && is_arithmetic<T>::value> {};
331 
332 // is_bool
333 template <typename T>
335  : std::bool_constant<std::is_same_v<std::remove_cv_t<T>, bool>> {};
336 
337 template <typename T>
339  : std::bool_constant<is_vec<T>::value &&
340  is_scalar_bool<vector_element_t<T>>::value> {};
341 
342 template <typename T>
343 struct is_bool
344  : std::bool_constant<is_scalar_bool<vector_element_t<T>>::value> {};
345 
346 // is_boolean
347 template <int N> struct Boolean;
348 template <typename T> struct is_boolean : std::false_type {};
349 template <int N> struct is_boolean<Boolean<N>> : std::true_type {};
350 template <typename T> inline constexpr bool is_boolean_v = is_boolean<T>::value;
351 
352 // is_pointer
353 template <typename T> struct is_pointer_impl : std::false_type {};
354 
355 template <typename T> struct is_pointer_impl<T *> : std::true_type {};
356 
357 template <typename T, access::address_space Space,
358  access::decorated DecorateAddress>
359 struct is_pointer_impl<multi_ptr<T, Space, DecorateAddress>> : std::true_type {
360 };
361 
362 template <typename T>
363 struct is_pointer : is_pointer_impl<std::remove_cv_t<T>> {};
364 
365 template <typename T> inline constexpr bool is_pointer_v = is_pointer<T>::value;
366 
367 // is_multi_ptr
368 template <typename T> struct is_multi_ptr : std::false_type {};
369 
370 template <typename ElementType, access::address_space Space,
371  access::decorated IsDecorated>
372 struct is_multi_ptr<multi_ptr<ElementType, Space, IsDecorated>>
373  : std::true_type {};
374 
375 template <class T>
376 inline constexpr bool is_multi_ptr_v = is_multi_ptr<T>::value;
377 
378 // is_non_legacy_multi_ptr
379 template <typename T> struct is_non_legacy_multi_ptr : std::false_type {};
380 
381 template <typename ElementType, access::address_space Space>
383  multi_ptr<ElementType, Space, access::decorated::yes>> : std::true_type {};
384 
385 template <typename ElementType, access::address_space Space>
387  multi_ptr<ElementType, Space, access::decorated::no>> : std::true_type {};
388 
389 template <class T>
390 inline constexpr bool is_non_legacy_multi_ptr_v =
392 
393 // is_legacy_multi_ptr
394 template <typename T> struct is_legacy_multi_ptr : std::false_type {};
395 
396 template <typename ElementType, access::address_space Space>
398  multi_ptr<ElementType, Space, access::decorated::legacy>> : std::true_type {
399 };
400 
401 template <class T>
403 
404 // remove_pointer_t
405 template <typename T> struct remove_pointer_impl {
406  using type = T;
407 };
408 
409 template <typename T> struct remove_pointer_impl<T *> {
410  using type = T;
411 };
412 
413 template <typename T, access::address_space Space,
414  access::decorated DecorateAddress>
415 struct remove_pointer_impl<multi_ptr<T, Space, DecorateAddress>> {
416  using type = T;
417 };
418 
419 template <typename T>
420 struct remove_pointer : remove_pointer_impl<std::remove_cv_t<T>> {};
421 
422 template <typename T> using remove_pointer_t = typename remove_pointer<T>::type;
423 
424 // is_address_space_compliant
425 template <typename T, typename SpaceList>
426 struct is_address_space_compliant_impl : std::false_type {};
427 
428 template <typename T, typename SpaceList>
429 struct is_address_space_compliant_impl<T *, SpaceList> : std::true_type {};
430 
431 template <typename T, typename SpaceList, access::address_space Space,
432  access::decorated DecorateAddress>
433 struct is_address_space_compliant_impl<multi_ptr<T, Space, DecorateAddress>,
434  SpaceList>
435  : std::bool_constant<is_one_of_spaces<Space, SpaceList>::value> {};
436 
437 template <typename T, typename SpaceList>
439  : is_address_space_compliant_impl<std::remove_cv_t<T>, SpaceList> {};
440 
441 template <typename T, typename SpaceList>
442 inline constexpr bool is_address_space_compliant_v =
444 
445 // make_type_t
446 template <typename T, typename TL> struct make_type_impl {
448 };
449 
450 template <typename T, int N, typename TL> struct make_type_impl<vec<T, N>, TL> {
453 };
454 
455 template <typename T, typename TL>
457 
458 // make_larger_t
459 template <typename T, typename Enable = void> struct make_larger_impl;
460 template <typename T>
462  T, std::enable_if_t<is_contained<T, gtl::scalar_floating_list>::value, T>> {
464 };
465 
466 template <typename T>
468  T, std::enable_if_t<is_contained<T, gtl::scalar_signed_integer_list>::value,
469  T>> {
471 };
472 
473 template <typename T>
475  T, std::enable_if_t<
476  is_contained<T, gtl::scalar_unsigned_integer_list>::value, T>> {
478 };
479 
480 template <typename T, int N> struct make_larger_impl<vec<T, N>, vec<T, N>> {
484  static constexpr bool found = !std::is_same_v<upper_type, void>;
485  using type = std::conditional_t<found, new_type, void>;
486 };
487 
488 template <typename T, size_t N>
489 struct make_larger_impl<marray<T, N>, marray<T, N>> {
493  static constexpr bool found = !std::is_same_v<upper_type, void>;
494  using type = std::conditional_t<found, new_type, void>;
495 };
496 
497 template <typename T> struct make_larger {
499 };
500 
501 template <typename T> using make_larger_t = typename make_larger<T>::type;
502 
503 #if defined(RESTRICT_WRITE_ACCESS_TO_CONSTANT_PTR)
504 template <access::address_space AS, class DataT>
505 using const_if_const_AS =
506  typename std::conditional<AS == access::address_space::constant_space,
507  const DataT, DataT>::type;
508 #else
509 template <access::address_space AS, class DataT>
510 using const_if_const_AS = DataT;
511 #endif
512 
513 template <typename T> struct function_traits {};
514 
515 template <typename Ret, typename... Args> struct function_traits<Ret(Args...)> {
516  using ret_type = Ret;
517  using args_type = std::tuple<Args...>;
518 };
519 
520 // No first_type_t due to
521 // https://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430.
522 template <typename T, typename... Ts> struct first_type {
523  using type = T;
524 };
525 
526 template <typename T0, typename... Ts>
527 inline constexpr bool all_same_v = (... && std::is_same_v<T0, Ts>);
528 
529 // Example usage:
530 // using mapped = map_type<type_to_map, from0, /*->*/ to0,
531 // from1, /*->*/ to1,
532 // ...>
533 template <typename...> struct map_type {
534  using type = void;
535 };
536 
537 template <typename T, typename From, typename To, typename... Rest>
538 struct map_type<T, From, To, Rest...> {
539  using type = std::conditional_t<std::is_same_v<From, T>, To,
540  typename map_type<T, Rest...>::type>;
541 };
542 template <typename T, typename... Ts> constexpr bool CheckTypeIn() {
543  constexpr bool SameType[] = {
544  std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<Ts>>...};
545  // Replace with std::any_of with C++20.
546  for (size_t I = 0; I < sizeof...(Ts); ++I)
547  if (SameType[I])
548  return true;
549  return false;
550 }
551 
552 // NOTE: We need a constexpr variable definition for the constexpr functions
553 // as MSVC thinks function definitions are the same otherwise.
554 template <typename... Ts> constexpr bool check_type_in_v = CheckTypeIn<Ts...>();
555 
556 } // namespace detail
557 } // namespace _V1
558 } // namespace sycl
Provides a cross-platform math array class template that works on SYCL devices as well as in host C++...
Definition: marray.hpp:49
class sycl::vec ///////////////////////// Provides a cross-patform vector class template that works e...
constexpr bool check_type_in_v
typename change_base_type< T, B >::type change_base_type_t
constexpr bool is_scalar_arithmetic_v
constexpr bool is_pointer_v
constexpr bool is_boolean_v
typename T::value_type marray_element_t
constexpr bool is_marray_v
constexpr bool is_vec_v
constexpr bool is_gen_based_on_type_sizeof_v
constexpr bool is_non_legacy_multi_ptr_v
typename remove_pointer< T >::type remove_pointer_t
typename make_larger< T >::type make_larger_t
typename make_unsigned< T >::type make_unsigned_t
typename vector_element_impl< T >::type vector_element_impl_t
constexpr bool is_address_space_compliant_v
constexpr bool is_ext_vector_v
typename get_elem_type< T >::type get_elem_type_t
constexpr bool all_same_v
constexpr bool is_legacy_multi_ptr_v
constexpr bool CheckTypeIn()
typename vector_element< T >::type vector_element_t
typename copy_cv_qualifiers< T, R >::type copy_cv_qualifiers_t
typename make_signed< T >::type make_signed_t
constexpr bool is_multi_ptr_v
std::array< unsigned char, 16 > uuid_type
find_type_t< TypeList, is_type_size_equal, T > find_same_size_type_t
Definition: type_list.hpp:91
constexpr bool is_fixed_size_group_v
Definition: type_traits.hpp:26
find_type_t< TypeList, is_type_size_double_of, T > find_twice_as_large_type_t
Definition: type_list.hpp:95
std::integral_constant< int, V > int_constant
typename make_type_impl< T, TL >::type make_type_t
constexpr bool is_generic_group_v
Definition: type_traits.hpp:92
class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
constexpr bool is_group_v
sycl::detail::half_impl::half half
Definition: aliases.hpp:101
const void value_type
Definition: multi_ptr.hpp:457
Definition: access.hpp:18
typename copy_cv_qualifiers_impl< T, std::remove_cv_t< R > >::type type
typename make_larger_impl< base_type, base_type >::type upper_type
typename make_larger_impl< base_type, base_type >::type upper_type
std::conditional_t< found, new_type, void > type
typename make_larger_impl< T, T >::type type
std::make_signed_t< T > type
typename make_type_impl< T, TL >::type scalar_type
find_same_size_type_t< TL, T > type
std::make_unsigned_t< T > type
std::conditional_t< std::is_same_v< From, T >, To, typename map_type< T, Rest... >::type > type
copy_cv_qualifiers_t< T, vector_element_impl_t< std::remove_cv_t< T > >> type