diff --git a/thrust/testing/device_ptr.cu b/thrust/testing/device_ptr.cu index 65e4021f94d..6ace3a2aa7d 100644 --- a/thrust/testing/device_ptr.cu +++ b/thrust/testing/device_ptr.cu @@ -1,8 +1,17 @@ #include #include +#include + +#include + #include +#ifdef __cpp_lib_concepts +static_assert(std::indirectly_writable, uint8_t>); +#endif // __cpp_lib_concepts +static_assert(cuda::std::indirectly_writable, uint8_t>); + void TestDevicePointerManipulation() { thrust::device_vector data(5); diff --git a/thrust/testing/device_reference.cu b/thrust/testing/device_reference.cu index 24cb5d7e3c9..4d2c88fa4f9 100644 --- a/thrust/testing/device_reference.cu +++ b/thrust/testing/device_reference.cu @@ -58,29 +58,47 @@ void TestDeviceReferenceAssignmentFromDeviceReference() { // test same types using T0 = int; - thrust::device_vector v0(2, 0); + thrust::device_vector v0{0, 0}; thrust::device_reference ref0 = v0[0]; thrust::device_reference ref1 = v0[1]; ref0 = 13; - ref1 = ref0; // ref1 equals 13 ASSERT_EQUAL(13, ref1); ASSERT_EQUAL(ref0, ref1); + // test const references + const thrust::device_reference cref0 = v0[0]; + const thrust::device_reference cref1 = v0[1]; + + cref0 = 13; + cref1 = cref0; + + // cref1 equals 13 + ASSERT_EQUAL(13, cref1); + ASSERT_EQUAL(cref0, cref1); + + // mix const and non-const references + ref0 = 12; + cref0 = ref0; + ASSERT_EQUAL(12, cref0); + + cref0 = 11; + ref0 = cref0; + ASSERT_EQUAL(11, cref0); + // test different types using T1 = float; - thrust::device_vector v1(1, 0.0f); + thrust::device_vector v1{0.0f}; thrust::device_reference ref2 = v1[0]; - ref2 = ref1; + ref2 = ref0; - // ref2 equals 13.0f - ASSERT_EQUAL(13.0f, ref2); + // ref2 equals 11.0f + ASSERT_EQUAL(11.0f, ref2); ASSERT_EQUAL(ref0, ref2); - ASSERT_EQUAL(ref1, ref2); } DECLARE_UNITTEST(TestDeviceReferenceAssignmentFromDeviceReference); diff --git a/thrust/thrust/detail/reference.h b/thrust/thrust/detail/reference.h index 057f0229bbd..0163afaedca 100644 --- a/thrust/thrust/detail/reference.h +++ b/thrust/thrust/detail/reference.h @@ -107,7 +107,7 @@ class reference * * \return *this. */ - _CCCL_HOST_DEVICE derived_type& operator=(reference const& other) + _CCCL_HOST_DEVICE const derived_type& operator=(reference const& other) const { assign_from(&other); return derived(); @@ -124,21 +124,14 @@ class reference * * \return *this. */ - template - _CCCL_HOST_DEVICE - /*! \cond - */ - typename std::enable_if< - std::is_convertible::pointer, pointer>::value, - /*! \endcond - */ - derived_type& - /*! \cond - */ - >::type - /*! \endcond - */ - operator=(reference const& other) + template < + typename OtherElement, + typename OtherPointer, + typename OtherDerived, + ::cuda::std::enable_if_t< + ::cuda::std::is_convertible_v::pointer, pointer>, + int> = 0> + _CCCL_HOST_DEVICE const derived_type& operator=(reference const& other) const { assign_from(&other); return derived(); @@ -150,7 +143,7 @@ class reference * * \return *this. */ - _CCCL_HOST_DEVICE derived_type& operator=(value_type const& rhs) + _CCCL_HOST_DEVICE const derived_type& operator=(value_type const& rhs) const { assign_from(&rhs); return derived(); @@ -323,6 +316,11 @@ class reference return static_cast(*this); } + _CCCL_HOST_DEVICE const derived_type& derived() const + { + return static_cast(*this); + } + template _CCCL_HOST_DEVICE value_type convert_to_value_type(System* system) const { @@ -340,14 +338,14 @@ class reference } template - _CCCL_HOST_DEVICE void assign_from(System0* system0, System1* system1, OtherPointer src) + _CCCL_HOST_DEVICE void assign_from(System0* system0, System1* system1, OtherPointer src) const { using thrust::system::detail::generic::select_system; strip_const_assign_value(select_system(*system0, *system1), src); } template - _CCCL_HOST_DEVICE void assign_from(OtherPointer src) + _CCCL_HOST_DEVICE void assign_from(OtherPointer src) const { // Avoid default-constructing systems; instead, just use a null pointer // for dispatch. This assumes that `get_value` will not access any system @@ -358,7 +356,7 @@ class reference } template - _CCCL_HOST_DEVICE void strip_const_assign_value(System const& system, OtherPointer src) + _CCCL_HOST_DEVICE void strip_const_assign_value(System const& system, OtherPointer src) const { System& non_const_system = const_cast(system); @@ -445,7 +443,7 @@ class tagged_reference * * \return *this. */ - _CCCL_HOST_DEVICE tagged_reference& operator=(tagged_reference const& other) + _CCCL_HOST_DEVICE const tagged_reference& operator=(tagged_reference const& other) const { return base_type::operator=(other); } @@ -461,7 +459,7 @@ class tagged_reference * \return *this. */ template - _CCCL_HOST_DEVICE tagged_reference& operator=(tagged_reference const& other) + _CCCL_HOST_DEVICE const tagged_reference& operator=(tagged_reference const& other) const { return base_type::operator=(other); } @@ -472,7 +470,7 @@ class tagged_reference * * \return *this. */ - _CCCL_HOST_DEVICE tagged_reference& operator=(value_type const& rhs) + _CCCL_HOST_DEVICE const tagged_reference& operator=(value_type const& rhs) const { return base_type::operator=(rhs); } diff --git a/thrust/thrust/device_reference.h b/thrust/thrust/device_reference.h index 7d457b20bfa..14b2c991809 100644 --- a/thrust/thrust/device_reference.h +++ b/thrust/thrust/device_reference.h @@ -203,6 +203,8 @@ class device_reference : public thrust::reference, thru */ using pointer = typename super_t::pointer; + device_reference(const device_reference& other) = default; + /*! This copy constructor accepts a const reference to another * \p device_reference. After this \p device_reference is constructed, * it shall refer to the same object as \p other. @@ -273,6 +275,11 @@ class device_reference : public thrust::reference, thru : super_t(ptr) {} + _CCCL_HOST_DEVICE const device_reference& operator=(const device_reference& other) const + { + return super_t::operator=(other); + } + /*! This assignment operator assigns the value of the object referenced by * the given \p device_reference to the object referenced by this * \p device_reference. @@ -281,7 +288,7 @@ class device_reference : public thrust::reference, thru * \return *this */ template - _CCCL_HOST_DEVICE device_reference& operator=(const device_reference& other) + _CCCL_HOST_DEVICE const device_reference& operator=(const device_reference& other) const { return super_t::operator=(other); } @@ -292,7 +299,7 @@ class device_reference : public thrust::reference, thru * \param x The value to assign from. * \return *this */ - _CCCL_HOST_DEVICE device_reference& operator=(const value_type& x) + _CCCL_HOST_DEVICE const device_reference& operator=(const value_type& x) const { return super_t::operator=(x); }