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