From 8c8fe5ef2d26a8258862aeca2702c05df1639351 Mon Sep 17 00:00:00 2001 From: Patrick Stotko <stotko@cs.uni-bonn.de> Date: Wed, 17 Jul 2024 08:10:39 +0200 Subject: [PATCH] utility: Add custom pair implementation --- src/stdgpu/impl/utility_detail.h | 100 +++++++++++++++++++++ src/stdgpu/utility.h | 150 ++++++++++++++++++++++++++++++- 2 files changed, 248 insertions(+), 2 deletions(-) diff --git a/src/stdgpu/impl/utility_detail.h b/src/stdgpu/impl/utility_detail.h index a913768d6..748802ca7 100644 --- a/src/stdgpu/impl/utility_detail.h +++ b/src/stdgpu/impl/utility_detail.h @@ -19,6 +19,106 @@ namespace stdgpu { +template <typename T1, typename T2> +template < + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_default_constructible_v<T1>&& std::is_default_constructible_v<T2>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair() + : first() + , second() +{ +} + +template <typename T1, typename T2> +template <STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_copy_constructible_v<T1>&& std::is_copy_constructible_v<T2>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(const T1& x, const T2& y) + : first(x) + , second(y) +{ +} + +template <typename T1, typename T2> +template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(U1&& x, U2&& y) + : first(forward<U1>(x)) + , second(forward<U2>(y)) +{ +} + +template <typename T1, typename T2> +template <typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1&>&& std::is_constructible_v<T2, U2&>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(pair<U1, U2>& p) + : first(p.first) + , second(p.second) +{ +} + +template <typename T1, typename T2> +template <typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF( + std::is_constructible_v<T1, const U1&>&& std::is_constructible_v<T2, const U2&>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(const pair<U1, U2>& p) + : first(p.first) + , second(p.second) +{ +} + +template <typename T1, typename T2> +template <typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(pair<U1, U2>&& p) + : first(forward<U1>(p.first)) + , second(forward<U2>(p.second)) +{ +} + +template <typename T1, typename T2> +template <typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> +constexpr STDGPU_HOST_DEVICE +pair<T1, T2>::pair(const pair<U1, U2>&& p) + : first(forward<const U1>(p.first)) + , second(forward<const U2>(p.second)) +{ +} + +template <typename T1, typename T2> +template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF( + std::is_assignable_v<T1&, const U1&>&& std::is_assignable_v<T2&, const U2&>)> +constexpr STDGPU_HOST_DEVICE pair<T1, T2>& +pair<T1, T2>::operator=(const pair<U1, U2>& p) +{ + first = p.first; + second = p.second; + return *this; +} + +template <typename T1, typename T2> +template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_assignable_v<T1&, U1>&& std::is_assignable_v<T2&, U2>)> +constexpr STDGPU_HOST_DEVICE pair<T1, T2>& +pair<T1, T2>::operator=(pair<U1, U2>&& p) +{ + first = forward<U1>(p.first); + second = forward<U1>(p.second); + return *this; +} + template <class T> constexpr STDGPU_HOST_DEVICE T&& forward(std::remove_reference_t<T>& t) noexcept diff --git a/src/stdgpu/utility.h b/src/stdgpu/utility.h index 61e697e5b..04c2afae5 100644 --- a/src/stdgpu/utility.h +++ b/src/stdgpu/utility.h @@ -25,10 +25,10 @@ * \file stdgpu/utility.h */ -#include <thrust/pair.h> #include <type_traits> #include <stdgpu/platform.h> +#include <stdgpu/type_traits.h> namespace stdgpu { @@ -40,7 +40,153 @@ namespace stdgpu * \brief A pair of two values of potentially different types */ template <typename T1, typename T2> -using pair = thrust::pair<T1, T2>; +struct pair +{ + using first_type = T1; /**< T1 */ + using second_type = T2; /**< T2 */ + + /** + * \brief Default Destructor + */ + ~pair() = default; + + /** + * \brief Constructor + */ + template <STDGPU_DETAIL_OVERLOAD_IF(std::is_default_constructible_v<T1>&& std::is_default_constructible_v<T2>)> + constexpr STDGPU_HOST_DEVICE + pair(); + + /** + * \brief Constructor + * \param[in] x The new first element + * \param[in] y The new second element + */ + template <STDGPU_DETAIL_OVERLOAD_IF(std::is_copy_constructible_v<T1>&& std::is_copy_constructible_v<T2>)> + constexpr STDGPU_HOST_DEVICE + pair(const T1& x, const T2& y); + + /** + * \brief Constructor + * \tparam U1 The type of the first element + * \tparam U2 The type of the second element + * \param[in] x The new first element + * \param[in] y The new second element + */ + template <class U1 = T1, + class U2 = T2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> + constexpr STDGPU_HOST_DEVICE + pair(U1&& x, U2&& y); + + /** + * \brief Copy constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The pair to copy from + */ + template <typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1&>&& std::is_constructible_v<T2, U2&>)> + constexpr STDGPU_HOST_DEVICE + pair(pair<U1, U2>& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Copy constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The copied pair + */ + template < + typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, const U1&>&& std::is_constructible_v<T2, const U2&>)> + constexpr STDGPU_HOST_DEVICE + pair(const pair<U1, U2>& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Move constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + */ + template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> + constexpr STDGPU_HOST_DEVICE + pair(pair<U1, U2>&& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Move constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + */ + template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)> + constexpr STDGPU_HOST_DEVICE + pair(const pair<U1, U2>&& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Default copy constructor + * \param[in] p The copied pair + */ + pair(const pair& p) = default; + + /** + * \brief Default move constructor + * \param[in] p The moved pair + */ + pair(pair&& p) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + + /** + * \brief Default copy assignment operator + * \param[in] p The pair to copy from + * \return *this + */ + pair& + operator=(const pair& p) = default; + + /** + * \brief Copy assignment operator + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The pair to copy from + * \return *this + */ + template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_assignable_v<T1&, const U1&>&& std::is_assignable_v<T2&, const U2&>)> + constexpr STDGPU_HOST_DEVICE pair& + operator=(const pair<U1, U2>& p); + + /** + * \brief Default move assignment operator + * \param[in] p The moved pair + * \return *this + */ + pair& + operator=(pair&& p) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + + /** + * \brief Move assignment operator + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + * \return *this + */ + template <class U1, + class U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_assignable_v<T1&, U1>&& std::is_assignable_v<T2&, U2>)> + constexpr STDGPU_HOST_DEVICE pair& + operator=(pair<U1, U2>&& p); + + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + first_type first; /**< First element of pair */ + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + second_type second; /**< Second element of pair */ +}; /** * \ingroup utility