58
58
#include < array>
59
59
#include < cmath>
60
60
#include < cstring>
61
+ #include < optional>
62
+ #include < variant>
61
63
#ifndef __SYCL_DEVICE_ONLY__
62
64
#include < cfenv>
63
65
#endif
@@ -2393,6 +2395,12 @@ __SYCL_DECLARE_FLOAT_VECTOR_CONVERTERS(double)
2393
2395
template <typename T, typename = void>
2394
2396
struct is_device_copyable : std::false_type {};
2395
2397
2398
+ // NOTE: this specialization is a candidate for all T such that T is trivially
2399
+ // copyable, including std::array<T, N>, std::optional<T>, std::variant<T>,
2400
+ // sycl::marray<T> and T[N]. Thus, specializations for all these mentioned
2401
+ // types are guarded by `std::enable_if_t<!std::is_trivially_copyable<...>>`
2402
+ // so that they are candidates only for non-trivially-copyable types.
2403
+ // Otherwise, there are several candidates and the compiler can't decide.
2396
2404
template <typename T>
2397
2405
struct is_device_copyable<
2398
2406
T, std::enable_if_t<std::is_trivially_copyable<T>::value>>
@@ -2401,16 +2409,56 @@ struct is_device_copyable<
2401
2409
template <typename T>
2402
2410
inline constexpr bool is_device_copyable_v = is_device_copyable<T>::value;
2403
2411
2412
+ // std::array<T, 0> is implicitly device copyable type.
2413
+ template <typename T>
2414
+ struct is_device_copyable<std::array<T, 0>> : std::true_type {};
2415
+
2416
+ // std::array<T, N> is implicitly device copyable type if T is device copyable
2417
+ template <typename T, std::size_t N>
2418
+ struct is_device_copyable<
2419
+ std::array<T, N>,
2420
+ std::enable_if_t<!std::is_trivially_copyable<std::array<T, N>>::value>>
2421
+ : is_device_copyable<T> {};
2422
+
2423
+ // std::optional<T> is implicitly device copyable type if T is device copyable
2424
+ template <typename T>
2425
+ struct is_device_copyable<
2426
+ std::optional<T>,
2427
+ std::enable_if_t<!std::is_trivially_copyable<std::optional<T>>::value>>
2428
+ : is_device_copyable<T> {};
2429
+
2430
+ // std::pair<T1, T2> is implicitly device copyable type if T1 and T2 are device
2431
+ // copyable
2432
+ template <typename T1, typename T2>
2433
+ struct is_device_copyable<
2434
+ std::pair<T1, T2>,
2435
+ std::enable_if_t<!std::is_trivially_copyable<std::pair<T1, T2>>::value>>
2436
+ : detail::bool_constant<is_device_copyable<T1>::value &&
2437
+ is_device_copyable<T2>::value> {};
2438
+
2404
2439
// std::tuple<> is implicitly device copyable type.
2405
2440
template <> struct is_device_copyable<std::tuple<>> : std::true_type {};
2406
2441
2407
2442
// std::tuple<Ts...> is implicitly device copyable type if each type T of Ts...
2408
2443
// is device copyable.
2409
2444
template <typename T, typename... Ts>
2410
- struct is_device_copyable<std::tuple<T, Ts...>>
2445
+ struct is_device_copyable<
2446
+ std::tuple<T, Ts...>,
2447
+ std::enable_if_t<!std::is_trivially_copyable<std::tuple<T, Ts...>>::value>>
2411
2448
: detail::bool_constant<is_device_copyable<T>::value &&
2412
2449
is_device_copyable<std::tuple<Ts...>>::value> {};
2413
2450
2451
+ // std::variant<> is implicitly device copyable type
2452
+ template <> struct is_device_copyable<std::variant<>> : std::true_type {};
2453
+
2454
+ // std::variant<Ts...> is implicitly device copyable type if each type T of
2455
+ // Ts... is device copyable
2456
+ template <typename... Ts>
2457
+ struct is_device_copyable<
2458
+ std::variant<Ts...>,
2459
+ std::enable_if_t<!std::is_trivially_copyable<std::variant<Ts...>>::value>>
2460
+ : is_device_copyable<Ts...> {};
2461
+
2414
2462
// marray is device copyable if element type is device copyable and it is also
2415
2463
// not trivially copyable (if the element type is trivially copyable, the marray
2416
2464
// is device copyable by default).
@@ -2420,6 +2468,18 @@ struct is_device_copyable<
2420
2468
!std::is_trivially_copyable<T>::value>>
2421
2469
: std::true_type {};
2422
2470
2471
+ // array is device copyable if element type is device copyable
2472
+ template <typename T, std::size_t N>
2473
+ struct is_device_copyable<
2474
+ T[N], std::enable_if_t<!std::is_trivially_copyable<T>::value>>
2475
+ : is_device_copyable<T> {};
2476
+
2477
+ template <typename T>
2478
+ struct is_device_copyable<
2479
+ T, std::enable_if_t<!std::is_trivially_copyable<T>::value &&
2480
+ (std::is_const_v<T> || std::is_volatile_v<T>)>>
2481
+ : is_device_copyable<std::remove_cv_t<T>> {};
2482
+
2423
2483
namespace detail {
2424
2484
template <typename T, typename = void>
2425
2485
struct IsDeprecatedDeviceCopyable : std::false_type {};
@@ -2433,9 +2493,13 @@ struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020")
2433
2493
std::is_trivially_destructible<T>::value &&
2434
2494
!is_device_copyable<T>::value>> : std::true_type {};
2435
2495
2496
+ template <typename T, int N>
2497
+ struct __SYCL2020_DEPRECATED("This type isn' t device copyable in SYCL 2020 " )
2498
+ IsDeprecatedDeviceCopyable<T[N]> : IsDeprecatedDeviceCopyable<T> {};
2499
+
2436
2500
#ifdef __SYCL_DEVICE_ONLY__
2437
- // Checks that the fields of the type T with indices 0 to (NumFieldsToCheck - 1)
2438
- // are device copyable.
2501
+ // Checks that the fields of the type T with indices 0 to (NumFieldsToCheck -
2502
+ // 1) are device copyable.
2439
2503
template <typename T, unsigned NumFieldsToCheck>
2440
2504
struct CheckFieldsAreDeviceCopyable
2441
2505
: CheckFieldsAreDeviceCopyable<T, NumFieldsToCheck - 1> {
0 commit comments