@@ -386,31 +386,55 @@ using AlignBytes CCCL_DEPRECATED_BECAUSE("Use alignof(T) directly") = detail::Al
386386template <typename T>
387387struct UnitWord
388388{
389- static constexpr auto ALIGN_BYTES = alignof (T);
389+ CCCL_DEPRECATED static constexpr auto ALIGN_BYTES = alignof (T);
390390
391391 template <typename Unit>
392- struct IsMultiple
392+ struct CCCL_DEPRECATED IsMultiple
393393 {
394394 static constexpr auto UNIT_ALIGN_BYTES = alignof (Unit);
395395 static constexpr bool IS_MULTIPLE =
396- (sizeof (T) % sizeof (Unit) == 0 ) && (int (ALIGN_BYTES ) % int (UNIT_ALIGN_BYTES) == 0 );
396+ (sizeof (T) % sizeof (Unit) == 0 ) && (int (alignof (T) ) % int (UNIT_ALIGN_BYTES) == 0 );
397397 };
398398
399+ // MSVC < 19.39 gets an internal compile error on the __is_multiple variable template below, so use a struct instead
400+ # if _CCCL_COMPILER(MSVC, <, 19, 39)
401+ template <typename Unit>
402+ using __is_multiple =
403+ ::cuda::std::bool_constant<(sizeof (T) % sizeof (Unit) == 0 ) && (alignof (T) % alignof (Unit) == 0 )>;
404+
399405 // / Largest shuffle word such that sizeof(T) % sizeof(W) == 0 and alignof(W) <= alignof(T)
400406 using ShuffleWord =
401- ::cuda::std::_If<IsMultiple <int >::IS_MULTIPLE ,
407+ ::cuda::std::_If<__is_multiple <int >::value ,
402408 unsigned int ,
403- ::cuda::std::_If<IsMultiple <short >::IS_MULTIPLE , unsigned short , unsigned char >>;
409+ ::cuda::std::_If<__is_multiple <short >::value , unsigned short , unsigned char >>;
404410
405411 // / Largest volatile word such that sizeof(T) % sizeof(W) == 0 and alignof(W) <= alignof(T)
406- using VolatileWord = ::cuda::std::_If<IsMultiple <long long >::IS_MULTIPLE , unsigned long long , ShuffleWord>;
412+ using VolatileWord = ::cuda::std::_If<__is_multiple <long long >::value , unsigned long long , ShuffleWord>;
407413
408414 // / Largest memory-access word such that sizeof(T) % sizeof(W) == 0 and alignof(W) <= alignof(T)
409- using DeviceWord = ::cuda::std::_If<IsMultiple <longlong2 >::IS_MULTIPLE , ulonglong2 , VolatileWord>;
415+ using DeviceWord = ::cuda::std::_If<__is_multiple <longlong2 >::value , ulonglong2 , VolatileWord>;
410416
411417 // / Biggest texture reference word such that sizeof(T) % sizeof(W) == 0 and alignof(W) <= alignof(T)
412- using TextureWord = ::cuda::std::
413- _If<IsMultiple<int4 >::IS_MULTIPLE, uint4 , ::cuda::std::_If<IsMultiple<int2 >::IS_MULTIPLE, uint2 , ShuffleWord>>;
418+ using TextureWord =
419+ ::cuda::std::_If<__is_multiple<int4 >::value, uint4 , ::cuda::std::_If<__is_multiple<int2 >::value, uint2 , ShuffleWord>>;
420+ # else // _CCCL_COMPILER(MSVC, <, 19, 39)
421+ template <typename Unit>
422+ static constexpr bool __is_multiple = (sizeof (T) % sizeof (Unit) == 0 ) && (alignof (T) % alignof (Unit) == 0 );
423+
424+ // / Largest shuffle word evenly dividing T and not increasing the alignment
425+ using ShuffleWord = ::cuda::std::
426+ _If<__is_multiple<int >, unsigned int , ::cuda::std::_If<__is_multiple<short >, unsigned short , unsigned char >>;
427+
428+ // / Largest volatile word evenly dividing T and not increasing the alignment
429+ using VolatileWord = ::cuda::std::_If<__is_multiple<long long >, unsigned long long , ShuffleWord>;
430+
431+ // / Largest memory-access word evenly dividing T and not increasing the alignment
432+ using DeviceWord = ::cuda::std::_If<__is_multiple<longlong2 >, ulonglong2 , VolatileWord>;
433+
434+ // / Biggest texture reference word evenly dividing T and not increasing the alignment
435+ using TextureWord =
436+ ::cuda::std::_If<__is_multiple<int4 >, uint4 , ::cuda::std::_If<__is_multiple<int2 >, uint2 , ShuffleWord>>;
437+ # endif // _CCCL_COMPILER(MSVC, <, 19, 39)
414438};
415439
416440// float2 specialization workaround (for SM10-SM13)
@@ -644,18 +668,18 @@ CUB_DEFINE_VECTOR_TYPE(bool, uchar)
644668 * Wrapper types
645669 ******************************************************************************/
646670
647- /* *
648- * \brief A storage-backing wrapper that allows types with non-trivial constructors to be aliased in unions
649- */
671+ // ! \brief A storage-backing wrapper that allows types with non-trivial constructors to be aliased in unions. Has the
672+ // ! same size as T.
650673template <typename T>
651674struct Uninitialized
652675{
653- // / Largest memory-access word such that sizeof(T) % sizeof(W) == 0 and alignof(W) <= alignof(T)
676+ // / Largest memory-access word evenly dividing T and not increasing the alignment
654677 using DeviceWord = typename UnitWord<T>::DeviceWord;
655678
656679 static constexpr ::cuda::std::size_t DATA_SIZE = sizeof (T);
657680 static constexpr ::cuda::std::size_t WORD_SIZE = sizeof (DeviceWord);
658681 static constexpr ::cuda::std::size_t WORDS = DATA_SIZE / WORD_SIZE;
682+ static_assert (DATA_SIZE % WORDS == 0 );
659683
660684 // / Backing storage
661685 DeviceWord storage[WORDS];
0 commit comments