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_unqual {
160  using type = T;
161 };
162 template <typename T, size_t N> struct get_elem_type_unqual<marray<T, N>> {
163  using type = T;
164 };
165 template <typename T, int N> struct get_elem_type_unqual<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_unqual<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_unqual<multi_ptr<ElementType, Space, DecorateAddress>> {
178  using type = ElementType;
179 };
180 
181 template <typename ElementType> struct get_elem_type_unqual<ElementType *> {
182  using type = ElementType;
183 };
184 
185 template <typename T, typename = void>
186 struct is_ext_vector : std::false_type {};
187 
188 template <typename T>
190  T, std::void_t<decltype(__builtin_reduce_max(std::declval<T>()))>>
191  : std::true_type {};
192 
193 template <typename T>
194 inline constexpr bool is_ext_vector_v = is_ext_vector<T>::value;
195 
196 template <typename T>
197 struct get_elem_type_unqual<T, std::enable_if_t<is_ext_vector_v<T>>> {
198  using type = decltype(__builtin_reduce_max(std::declval<T>()));
199 };
200 
201 template <typename T>
202 struct get_elem_type : get_elem_type_unqual<std::remove_cv_t<T>> {};
203 
204 template <typename T> using get_elem_type_t = typename get_elem_type<T>::type;
205 
206 // change_base_type_t
207 template <typename T, typename B> struct change_base_type {
208  using type = B;
209 };
210 
211 template <typename T, int N, typename B> struct change_base_type<vec<T, N>, B> {
212  using type = vec<B, N>;
213 };
214 
215 template <typename T, typename B>
217 
218 // Applies the same the cv-qualifiers from T type to R type
219 template <typename T, typename R> struct copy_cv_qualifiers_impl {
220  using type = R;
221 };
222 
223 template <typename T, typename R> struct copy_cv_qualifiers_impl<const T, R> {
224  using type = const R;
225 };
226 
227 template <typename T, typename R>
228 struct copy_cv_qualifiers_impl<volatile T, R> {
229  using type = volatile R;
230 };
231 
232 template <typename T, typename R>
233 struct copy_cv_qualifiers_impl<const volatile T, R> {
234  using type = const volatile R;
235 };
236 
237 template <typename T, typename R> struct copy_cv_qualifiers {
239 };
240 
241 // make_signed with support SYCL vec class
242 template <typename T> struct make_signed {
243  using type = std::make_signed_t<T>;
244 };
245 template <typename T> using make_signed_t = typename make_signed<T>::type;
246 template <class T> struct make_signed<const T> {
247  using type = const make_signed_t<T>;
248 };
249 template <class T, int N> struct make_signed<vec<T, N>> {
251 };
252 template <typename VecT, typename OperationLeftT, typename OperationRightT,
253  template <typename> class OperationCurrentT, int... Indexes>
254 struct make_signed<SwizzleOp<VecT, OperationLeftT, OperationRightT,
255  OperationCurrentT, Indexes...>> {
257 };
258 template <class T, std::size_t N> struct make_signed<marray<T, N>> {
260 };
261 
262 // make_unsigned with support SYCL vec class
263 template <typename T> struct make_unsigned {
264  using type = std::make_unsigned_t<T>;
265 };
266 template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
267 template <class T> struct make_unsigned<const T> {
268  using type = const make_unsigned_t<T>;
269 };
270 template <class T, int N> struct make_unsigned<vec<T, N>> {
272 };
273 template <typename VecT, typename OperationLeftT, typename OperationRightT,
274  template <typename> class OperationCurrentT, int... Indexes>
275 struct make_unsigned<SwizzleOp<VecT, OperationLeftT, OperationRightT,
276  OperationCurrentT, Indexes...>> {
278 };
279 template <class T, std::size_t N> struct make_unsigned<marray<T, N>> {
281 };
282 
283 // Checks that sizeof base type of T equal N and T satisfies S<T>::value
284 template <typename T, int N, template <typename> class S>
285 inline constexpr bool is_gen_based_on_type_sizeof_v =
286  S<T>::value && (sizeof(vector_element_t<T>) == N);
287 
288 template <typename> struct is_vec : std::false_type {};
289 template <typename T, int N> struct is_vec<sycl::vec<T, N>> : std::true_type {};
290 
291 template <typename T> constexpr bool is_vec_v = is_vec<T>::value;
292 
293 template <typename> struct get_vec_size {
294  static constexpr int size = 1;
295 };
296 
297 template <typename T, int N> struct get_vec_size<sycl::vec<T, N>> {
298  static constexpr int size = N;
299 };
300 
301 // is_swizzle
302 template <typename> struct is_swizzle : std::false_type {};
303 template <typename VecT, typename OperationLeftT, typename OperationRightT,
304  template <typename> class OperationCurrentT, int... Indexes>
305 struct is_swizzle<SwizzleOp<VecT, OperationLeftT, OperationRightT,
306  OperationCurrentT, Indexes...>> : std::true_type {};
307 
308 template <typename T> constexpr bool is_swizzle_v = is_swizzle<T>::value;
309 
310 // is_swizzle_or_vec_v
311 
312 template <typename T>
313 constexpr bool is_vec_or_swizzle_v = is_vec_v<T> || is_swizzle_v<T>;
314 
315 // is_marray
316 template <typename> struct is_marray : std::false_type {};
317 template <typename T, size_t N>
318 struct is_marray<sycl::marray<T, N>> : std::true_type {};
319 
320 template <typename T> constexpr bool is_marray_v = is_marray<T>::value;
321 
322 // is_integral
323 template <typename T>
324 struct is_integral : std::is_integral<get_elem_type_t<T>> {};
325 
326 // is_floating_point
327 template <typename T>
328 struct is_floating_point_impl : std::is_floating_point<T> {};
329 
330 template <> struct is_floating_point_impl<half> : std::true_type {};
331 
332 template <typename T>
334  : is_floating_point_impl<std::remove_cv_t<get_elem_type_t<T>>> {};
335 
336 // is_arithmetic
337 template <typename T>
339  : std::bool_constant<is_integral<T>::value || is_floating_point<T>::value> {
340 };
341 
342 template <typename T>
344  : std::bool_constant<!is_vec_or_swizzle_v<T> && !is_ext_vector_v<T> &&
345  !is_marray_v<T> && is_arithmetic<T>::value> {};
346 
347 template <typename T>
349 
350 template <typename T>
352  : std::bool_constant<(is_vec_or_swizzle_v<T> || is_ext_vector_v<T> ||
353  is_marray_v<T>) &&
354  is_arithmetic<T>::value> {};
355 
356 // is_bool
357 template <typename T>
359  : std::bool_constant<std::is_same_v<std::remove_cv_t<T>, bool>> {};
360 
361 template <typename T>
363  : std::bool_constant<is_vec<T>::value &&
364  is_scalar_bool<vector_element_t<T>>::value> {};
365 
366 template <typename T>
367 struct is_bool
368  : std::bool_constant<is_scalar_bool<vector_element_t<T>>::value> {};
369 
370 // is_boolean
371 template <int N> struct Boolean;
372 template <typename T> struct is_boolean : std::false_type {};
373 template <int N> struct is_boolean<Boolean<N>> : std::true_type {};
374 template <typename T> inline constexpr bool is_boolean_v = is_boolean<T>::value;
375 
376 // is_pointer
377 template <typename T> struct is_pointer_impl : std::false_type {};
378 
379 template <typename T> struct is_pointer_impl<T *> : std::true_type {};
380 
381 template <typename T, access::address_space Space,
382  access::decorated DecorateAddress>
383 struct is_pointer_impl<multi_ptr<T, Space, DecorateAddress>> : std::true_type {
384 };
385 
386 template <typename T>
387 struct is_pointer : is_pointer_impl<std::remove_cv_t<T>> {};
388 
389 template <typename T> inline constexpr bool is_pointer_v = is_pointer<T>::value;
390 
391 // is_multi_ptr
392 template <typename T> struct is_multi_ptr : std::false_type {};
393 
394 template <typename ElementType, access::address_space Space,
395  access::decorated IsDecorated>
396 struct is_multi_ptr<multi_ptr<ElementType, Space, IsDecorated>>
397  : std::true_type {};
398 
399 template <class T>
400 inline constexpr bool is_multi_ptr_v = is_multi_ptr<T>::value;
401 
402 // is_non_legacy_multi_ptr
403 template <typename T> struct is_non_legacy_multi_ptr : std::false_type {};
404 
405 template <typename ElementType, access::address_space Space>
407  multi_ptr<ElementType, Space, access::decorated::yes>> : std::true_type {};
408 
409 template <typename ElementType, access::address_space Space>
411  multi_ptr<ElementType, Space, access::decorated::no>> : std::true_type {};
412 
413 template <class T>
414 inline constexpr bool is_non_legacy_multi_ptr_v =
416 
417 // is_legacy_multi_ptr
418 template <typename T> struct is_legacy_multi_ptr : std::false_type {};
419 
420 template <typename ElementType, access::address_space Space>
422  multi_ptr<ElementType, Space, access::decorated::legacy>> : std::true_type {
423 };
424 
425 template <class T>
427 
428 // remove_pointer_t
429 template <typename T> struct remove_pointer_impl {
430  using type = T;
431 };
432 
433 template <typename T> struct remove_pointer_impl<T *> {
434  using type = T;
435 };
436 
437 template <typename T, access::address_space Space,
438  access::decorated DecorateAddress>
439 struct remove_pointer_impl<multi_ptr<T, Space, DecorateAddress>> {
440  using type = T;
441 };
442 
443 template <typename T>
444 struct remove_pointer : remove_pointer_impl<std::remove_cv_t<T>> {};
445 
446 template <typename T> using remove_pointer_t = typename remove_pointer<T>::type;
447 
448 // is_address_space_compliant
449 template <typename T, typename SpaceList>
450 struct is_address_space_compliant_impl : std::false_type {};
451 
452 template <typename T, typename SpaceList>
453 struct is_address_space_compliant_impl<T *, SpaceList> : std::true_type {};
454 
455 template <typename T, typename SpaceList, access::address_space Space,
456  access::decorated DecorateAddress>
457 struct is_address_space_compliant_impl<multi_ptr<T, Space, DecorateAddress>,
458  SpaceList>
459  : std::bool_constant<is_one_of_spaces<Space, SpaceList>::value> {};
460 
461 template <typename T, typename SpaceList>
463  : is_address_space_compliant_impl<std::remove_cv_t<T>, SpaceList> {};
464 
465 template <typename T, typename SpaceList>
466 inline constexpr bool is_address_space_compliant_v =
468 
469 // make_type_t
470 template <typename T, typename TL> struct make_type_impl {
472 };
473 
474 template <typename T, int N, typename TL> struct make_type_impl<vec<T, N>, TL> {
477 };
478 
479 template <typename T, typename TL>
481 
482 // make_larger_t
483 template <typename T, typename Enable = void> struct make_larger_impl;
484 template <typename T>
486  T, std::enable_if_t<is_contained<T, gtl::scalar_floating_list>::value, T>> {
488 };
489 
490 template <typename T>
492  T, std::enable_if_t<is_contained<T, gtl::scalar_signed_integer_list>::value,
493  T>> {
495 };
496 
497 template <typename T>
499  T, std::enable_if_t<
500  is_contained<T, gtl::scalar_unsigned_integer_list>::value, T>> {
502 };
503 
504 template <typename T, int N> struct make_larger_impl<vec<T, N>, vec<T, N>> {
508  static constexpr bool found = !std::is_same_v<upper_type, void>;
509  using type = std::conditional_t<found, new_type, void>;
510 };
511 
512 template <typename T, size_t N>
513 struct make_larger_impl<marray<T, N>, marray<T, N>> {
517  static constexpr bool found = !std::is_same_v<upper_type, void>;
518  using type = std::conditional_t<found, new_type, void>;
519 };
520 
521 template <typename T> struct make_larger {
523 };
524 
525 template <typename T> using make_larger_t = typename make_larger<T>::type;
526 
527 #if defined(RESTRICT_WRITE_ACCESS_TO_CONSTANT_PTR)
528 template <access::address_space AS, class DataT>
529 using const_if_const_AS =
530  typename std::conditional<AS == access::address_space::constant_space,
531  const DataT, DataT>::type;
532 #else
533 template <access::address_space AS, class DataT>
534 using const_if_const_AS = DataT;
535 #endif
536 
537 template <typename T> struct function_traits {};
538 
539 template <typename Ret, typename... Args> struct function_traits<Ret(Args...)> {
540  using ret_type = Ret;
541  using args_type = std::tuple<Args...>;
542 };
543 
544 // No first_type_t due to
545 // https://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430.
546 template <typename T, typename... Ts> struct first_type {
547  using type = T;
548 };
549 
550 template <typename T0, typename... Ts>
551 inline constexpr bool all_same_v = (... && std::is_same_v<T0, Ts>);
552 
553 // Example usage:
554 // using mapped = map_type<type_to_map, from0, /*->*/ to0,
555 // from1, /*->*/ to1,
556 // ...>
557 template <typename...> struct map_type {
558  using type = void;
559 };
560 
561 template <typename T, typename From, typename To, typename... Rest>
562 struct map_type<T, From, To, Rest...> {
563  using type = std::conditional_t<std::is_same_v<From, T>, To,
564  typename map_type<T, Rest...>::type>;
565 };
566 template <typename T, typename... Ts> constexpr bool CheckTypeIn() {
567  constexpr bool SameType[] = {
568  std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<Ts>>...};
569  // Replace with std::any_of with C++20.
570  for (size_t I = 0; I < sizeof...(Ts); ++I)
571  if (SameType[I])
572  return true;
573  return false;
574 }
575 
576 // NOTE: We need a constexpr variable definition for the constexpr functions
577 // as MSVC thinks function definitions are the same otherwise.
578 template <typename... Ts> constexpr bool check_type_in_v = CheckTypeIn<Ts...>();
579 
580 } // namespace detail
581 } // namespace _V1
582 } // 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
constexpr bool check_type_in_v
typename change_base_type< T, B >::type change_base_type_t
constexpr bool is_vec_or_swizzle_v
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
constexpr bool is_swizzle_v
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