Skip to content

Commit f13ff25

Browse files
committed
[libcu++] Fix __is_sequence definition for arguments framework
The current is_sequence definition is thoroughly broken. An iterator is not a sequence and neither is a pointer. The main problem here is that this precludes passing along iterators / pointers as values which is a reasonable use case. It also completely deviates from any standard handling in C++. Rather than reinventing the wheel in a bad way use standard terminology to determine what is a range and what not. A user can always wrap iterators and pointers into views and spans, so there is not need for the current definition
1 parent 2b21bec commit f13ff25

4 files changed

Lines changed: 34 additions & 38 deletions

File tree

libcudacxx/include/cuda/__argument/argument.h

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
#include <cuda/std/__algorithm/min_element.h>
2727
#include <cuda/std/__cccl/assert.h>
2828
#include <cuda/std/__iterator/readable_traits.h>
29+
#include <cuda/std/__ranges/concepts.h>
2930
#include <cuda/std/__type_traits/is_arithmetic.h>
31+
#include <cuda/std/__type_traits/is_array.h>
3032
#include <cuda/std/__type_traits/is_integer.h>
3133
#include <cuda/std/__type_traits/is_integral.h>
3234
#include <cuda/std/__type_traits/is_same.h>
@@ -75,23 +77,12 @@ template <class _Tp>
7577
using __element_type_of_t = typename __element_type_of<::cuda::std::remove_cvref_t<_Tp>>::type;
7678

7779
// =====================================================================
78-
// __is_sequence_v / __is_single_value_v
80+
// __is_sequence_v
7981
// =====================================================================
8082

8183
template <class _Tp>
8284
inline constexpr bool __is_sequence_v =
83-
!::cuda::std::is_same_v<::cuda::std::remove_cvref_t<_Tp>, __element_type_of_t<_Tp>>;
84-
85-
template <class _Tp>
86-
inline constexpr bool __is_single_value_v = !__is_sequence_v<_Tp>;
87-
88-
template <class _Tp, class = void>
89-
inline constexpr bool __is_iterable_v = false;
90-
91-
template <class _Tp>
92-
inline constexpr bool __is_iterable_v<_Tp,
93-
::cuda::std::void_t<decltype(::cuda::std::declval<const _Tp&>().begin()),
94-
decltype(::cuda::std::declval<const _Tp&>().end())>> = true;
85+
::cuda::std::is_array_v<::cuda::std::remove_cvref_t<_Tp>> || ::cuda::std::ranges::range<_Tp>;
9586

9687
// =====================================================================
9788
// __constant
@@ -121,7 +112,7 @@ struct __constant_sequence
121112
using value_type = ::cuda::std::remove_cvref_t<decltype(_Value)>;
122113
using __element_type = __element_type_of_t<value_type>;
123114

124-
static_assert(__is_sequence_v<value_type>, "constant sequence arguments must have a distinct element type");
115+
static_assert(__is_sequence_v<value_type>, "The value type of __constant_sequence must be a range or an array");
125116

126117
[[nodiscard]] _CCCL_API static constexpr value_type value() noexcept
127118
{
@@ -332,7 +323,7 @@ struct __immediate_sequence
332323

333324
_CCCL_API constexpr void __validate_value() const noexcept
334325
{
335-
if constexpr (__is_iterable_v<_Arg> && ::cuda::std::is_arithmetic_v<__element_type>)
326+
if constexpr (__is_sequence_v<_Arg> && ::cuda::std::is_arithmetic_v<__element_type>)
336327
{
337328
for (const auto& __a : __arg_)
338329
{
@@ -671,7 +662,7 @@ struct __traits_impl
671662
using element_type = __element_type_of_t<_Tp>;
672663
static constexpr bool is_constant = false;
673664
static constexpr bool is_deferred = false;
674-
static constexpr bool is_single_value = __is_single_value_v<_Tp>;
665+
static constexpr bool is_single_value = !__is_sequence_v<_Tp>;
675666
static constexpr element_type lowest = ::cuda::std::numeric_limits<element_type>::lowest();
676667
static constexpr element_type highest = (::cuda::std::numeric_limits<element_type>::max)();
677668
};

libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
#include <cuda/__argument_>
1212
#include <cuda/iterator>
1313
#include <cuda/std/array>
14+
#include <cuda/std/complex>
15+
#include <cuda/std/expected>
1416
#include <cuda/std/limits>
1517
#include <cuda/std/mdspan>
18+
#include <cuda/std/optional>
1619
#include <cuda/std/span>
20+
#include <cuda/std/tuple>
1721
#include <cuda/std/type_traits>
22+
#include <cuda/std/utility>
1823

1924
#include "test_macros.h"
2025

@@ -50,32 +55,32 @@ TEST_FUNC void test()
5055
{
5156
// --- __is_sequence_v / __is_single_value_v ---
5257

58+
// builtin and class type are not sequences
5359
static_assert(!cuda::__argument::__is_sequence_v<int>);
5460
static_assert(!cuda::__argument::__is_sequence_v<color>);
5561
static_assert(!cuda::__argument::__is_sequence_v<non_sequence_value>);
56-
static_assert(cuda::__argument::__is_sequence_v<int*>);
57-
static_assert(cuda::__argument::__is_sequence_v<cuda::counting_iterator<int>>);
62+
static_assert(!cuda::__argument::__is_sequence_v<range_like<int>>);
63+
static_assert(!cuda::__argument::__is_sequence_v<element_type_like<int>>);
64+
static_assert(!cuda::__argument::__is_sequence_v<value_type_like<int>>);
65+
static_assert(!cuda::__argument::__is_sequence_v<cuda::std::complex<float>>);
66+
static_assert(!cuda::__argument::__is_sequence_v<cuda::std::pair<float, int>>);
67+
static_assert(!cuda::__argument::__is_sequence_v<cuda::std::tuple<float, int>>);
68+
static_assert(!cuda::__argument::__is_sequence_v<cuda::std::optional<int>>);
69+
static_assert(!cuda::__argument::__is_sequence_v<cuda::std::expected<int, int>>);
70+
71+
// iterators are not sequences and need to be wrapped into a range
72+
static_assert(!cuda::__argument::__is_sequence_v<int*>);
73+
static_assert(!cuda::__argument::__is_sequence_v<cuda::counting_iterator<int>>);
74+
75+
// ranges and arrays are sequences
76+
static_assert(cuda::__argument::__is_sequence_v<int[]>);
77+
static_assert(cuda::__argument::__is_sequence_v<const int[]>);
78+
static_assert(cuda::__argument::__is_sequence_v<int[42]>);
79+
static_assert(cuda::__argument::__is_sequence_v<const int[42]>);
5880
static_assert(cuda::__argument::__is_sequence_v<cuda::std::span<int, 1>>);
5981
static_assert(cuda::__argument::__is_sequence_v<const cuda::std::span<int, 1>&>);
6082
static_assert(cuda::__argument::__is_sequence_v<cuda::std::span<int>>);
6183
static_assert(cuda::__argument::__is_sequence_v<cuda::std::array<int, 3>>);
62-
static_assert(cuda::__argument::__is_sequence_v<range_like<int>>);
63-
static_assert(cuda::__argument::__is_sequence_v<element_type_like<int>>);
64-
static_assert(cuda::__argument::__is_sequence_v<value_type_like<int>>);
65-
66-
static_assert(cuda::__argument::__is_single_value_v<int>);
67-
static_assert(cuda::__argument::__is_single_value_v<float>);
68-
static_assert(cuda::__argument::__is_single_value_v<double>);
69-
static_assert(cuda::__argument::__is_single_value_v<const int>);
70-
static_assert(cuda::__argument::__is_single_value_v<color>);
71-
static_assert(cuda::__argument::__is_single_value_v<non_sequence_value>);
72-
static_assert(!cuda::__argument::__is_single_value_v<int*>);
73-
static_assert(!cuda::__argument::__is_single_value_v<cuda::counting_iterator<int>>);
74-
static_assert(!cuda::__argument::__is_single_value_v<cuda::std::span<int, 1>>);
75-
static_assert(!cuda::__argument::__is_single_value_v<const cuda::std::span<int, 1>&>);
76-
static_assert(!cuda::__argument::__is_single_value_v<cuda::std::span<int>>);
77-
static_assert(!cuda::__argument::__is_single_value_v<cuda::std::span<int, 4>>);
78-
static_assert(!cuda::__argument::__is_single_value_v<cuda::std::array<int, 3>>);
7984

8085
// --- __element_type_of_t ---
8186

@@ -106,7 +111,7 @@ TEST_FUNC void test()
106111
// --- argument_traits: is_single_value ---
107112

108113
static_assert(cuda::__argument::__traits<int>::is_single_value);
109-
static_assert(!cuda::__argument::__traits<int*>::is_single_value);
114+
static_assert(cuda::__argument::__traits<int*>::is_single_value);
110115
static_assert(cuda::__argument::__traits<cuda::__argument::__immediate<int>>::is_single_value);
111116
static_assert(cuda::__argument::__traits<cuda::__argument::__immediate<int*>>::is_single_value);
112117
static_assert(

libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ TEST_FUNC constexpr bool test()
128128
// __is_single_value_v on unwrapped types
129129
{
130130
static_assert(
131-
cuda::__argument::__is_single_value_v<cuda::__argument::__traits<cuda::__argument::__immediate<int>>::value_type>);
131+
!cuda::__argument::__is_sequence_v<cuda::__argument::__traits<cuda::__argument::__immediate<int>>::value_type>);
132132
static_assert(
133133
!cuda::__argument::__traits<cuda::__argument::__immediate_sequence<cuda::std::span<int>>>::is_single_value);
134134
}

libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ TEST_FUNC void test()
113113
// Single value: scalar is single, sequence is not
114114
{
115115
static_assert(
116-
cuda::__argument::__is_single_value_v<cuda::__argument::__traits<cuda::__argument::__constant<42>>::value_type>);
116+
!cuda::__argument::__is_sequence_v<cuda::__argument::__traits<cuda::__argument::__constant<42>>::value_type>);
117117
#if TEST_HAS_CLASS_NTTP
118118
static_assert(!cuda::__argument::__traits<
119119
cuda::__argument::__constant_sequence<cuda::std::array<int, 3>{1, 2, 3}>>::is_single_value);

0 commit comments

Comments
 (0)