Skip to content

Rework constant_sequence taking a single auto NTTP to a variadic NTTP#9533

Open
codingwithmagga wants to merge 15 commits into
NVIDIA:mainfrom
codingwithmagga:9272_constant_sequence_variadic_nttp
Open

Rework constant_sequence taking a single auto NTTP to a variadic NTTP#9533
codingwithmagga wants to merge 15 commits into
NVIDIA:mainfrom
codingwithmagga:9272_constant_sequence_variadic_nttp

Conversation

@codingwithmagga

Copy link
Copy Markdown

Description

closes #9272

Refactors __constant_sequence to use a type + value-pack template (template <class T, T... Vs>) instead of a single class NTTP (template <auto _Value>). This removes the dependency on class non-type template parameters, making __constant_sequence usable in C++17 without the TEST_HAS_CLASS_NTTP guards that previously gated most of its tests.

A new factory function make_constant_sequence<Arr>() is added to construct a __constant_sequence from either a C-style array or a cuda::std::array with static storage duration, expanding the existing constexpr infrastructure (__unwrap, __lowest_, __highest_, __traits_impl) to match the new template signature.

Changes:

  • __constant_sequence<T, Vs...> replaces __constant_sequence<_Value>; value_type is now always cuda::std::array<T, sizeof...(Vs)>
  • make_constant_sequence<Arr>() factory supports both T[N] and cuda::std::array<T, N> inputs
  • __constant_sequence_compute_lowest/highest reimplemented as constexpr loops over a pack-expanded local array, replacing the std::min/max_element calls that required a runtime iterator
  • __unwrap now reconstructs the array from the pack: cuda::std::array<T, sizeof...(Vs)>{Vs...}
  • All TEST_HAS_CLASS_NTTP guards removed from the three affected test files; tests updated to use make_constant_sequence or direct __constant_sequence<T, Vs...> spelling

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@codingwithmagga codingwithmagga requested a review from a team as a code owner June 19, 2026 14:10
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jun 19, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Jun 19, 2026
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: db78928e-a43f-484e-a458-d6c5b54975d6

📥 Commits

Reviewing files that changed from the base of the PR and between 184a017 and 1cdd0fa.

📒 Files selected for processing (1)
  • libcudacxx/include/cuda/__argument/argument.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • libcudacxx/include/cuda/__argument/argument.h

Note: CodeRabbit is enabled on this repository as a convenience for maintainers and contributors. Use your best judgment when considering its review comments and suggestions — a suggested change may be inadequate, unnecessary, or safe to ignore.
Contributors are not expected to address every comment. Human reviews are what ultimately matter for merging.

Overview

This PR refactors cuda::args::__constant_sequence from a single auto non-type template parameter form into a variadic NTTP pack form template <class T, T... Vs>, eliminating the need for class-type NTTPs. This makes constant-sequence argument support work in C++17 without relying on TEST_HAS_CLASS_NTTP guards for __constant_sequence usage in the affected tests.

Key Changes

Core implementation (libcudacxx/include/cuda/__argument/argument.h)

  • Template refactor

    • Replaces __constant_sequence<_Value> with __constant_sequence<_Tp, _Vs...> where:
      • _Tp is the element type
      • _Vs... is the compile-time value pack
  • Canonical wrapper/unwrapping + traits

    • Updates wrapper detection and unwrapping for __constant_sequence<_Tp, _Vs...>.
    • __unwrap(const __constant_sequence<_Tp, _Vs...>&) now returns:
      • cuda::std::array<remove_cvref_t<_Tp>, sizeof...(_Vs)> initialized from {_Vs...}
    • Updates __traits_impl<__constant_sequence<_Tp, _Vs...>> so:
      • value_type = cuda::std::array<_Tp, sizeof...(_Vs)>
      • is_single_value = false
      • lowest / highest are computed from the _Vs... pack
  • Bounds computation rewritten

    • Refactors __constant_sequence_compute_lowest / __constant_sequence_compute_highest to accept _Tp, _Vs....
    • Handles the empty pack explicitly by returning:
      • __type_lowest<_Tp>() / __type_highest<_Tp>() (implemented via numeric_limits<_Tp>::lowest() / numeric_limits<_Tp>::max())
    • For non-empty packs, computes min/max by materializing a constexpr array from _Vs... and using min/max selection.
  • Factory/helper added

    • Adds __make_constant_sequence<Arr>() (+ __make_constant_sequence_impl) to build __constant_sequence<_Tp, _Vs...> by expanding elements from either:
      • a bounded C-style array reference, or
      • a cuda::std::array (static storage duration)
    • Includes a static_assert to reject unsupported array forms.
  • Free-function forwarding

    • Updates __lowest_ / __highest_ overloads to accept the new __constant_sequence<_Tp, _Vs...> signature and forward to the updated pack-based compute helpers.

Test Updates

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

    • Removes TEST_HAS_CLASS_NTTP-guarded constant-sequence assertions.
    • Adds unguarded validation for:
      • cuda::args::__constant_sequence<int, 1, 2, 3>
      • sequences produced by cuda::args::__make_constant_sequence from constexpr C arrays and cuda::std::array
    • Verifies value_type is cuda::std::array<int, 3> and lowest/highest are 1/3.
  • libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp

    • Switches constant-sequence construction to cuda::args::__make_constant_sequence<...>() for both C arrays and cuda::std::array.
    • Updates __unwrap and trait/value expectations to match the new cuda::std::array return type.
    • Updates bounds checks to include an explicit empty-sequence case for lowest/highest.
    • Removes the TEST_HAS_CLASS_NTTP-gated test that previously exercised the old constant-sequence form via __unwrap.
  • libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp

    • Updates constant/sequence construction to use cuda::args::__make_constant_sequence<...>() for shared/global segment-size scenarios.
    • Removes TEST_HAS_CLASS_NTTP-guarded usage of the old __constant_sequence form and replaces it with helper-based construction.
    • Adjusts the immediate-sequence setup to use constexpr arrays and marks seg_sizes as [[maybe_unused]].

Running the updated tests

libcu++ tests are run via LLVM’s lit (not individual CMake test targets). After configuring, invoke lit from build/latest/libcudacxx and point it at the relative path to the desired test (e.g., cuda/argument/argument_traits.pass.cpp).

Walkthrough

__constant_sequence now uses a variadic type/value-pack form, with factory helpers for C arrays and cuda::std::array. The wrapper, unwrap, bounds, and traits logic were updated, and tests were rewritten to use the new construction path without TEST_HAS_CLASS_NTTP.

Changes

Pack-based constant_sequence redesign

Layer / File(s) Summary
__constant_sequence definition and make_constant_sequence factory
libcudacxx/include/cuda/__argument/argument.h
Adds compile-time type-traits headers and cuda::std::array include; replaces the single-NTTP class with __constant_sequence<T, T... Vs>; introduces array-element-expansion helpers __make_constant_sequence_impl/__make_constant_sequence to convert C-style or cuda::std::array into the value pack.
Wrapper detection and __unwrap update
libcudacxx/include/cuda/__argument/argument.h
Updates __is_wrapper_v specialization to recognize __constant_sequence<T, Vs...>; replaces __unwrap to return cuda::std::array<remove_cvref_t<T>, sizeof...(Vs)> built from the pack.
Bounds computation and traits specialization
libcudacxx/include/cuda/__argument/argument.h
Rewrites __constant_sequence_compute_lowest/__constant_sequence_compute_highest for pack inputs and empty packs; updates __traits_impl, __lowest_, and __highest_ to match the new representation.
Test rewrites for new API
libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp, libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp, libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp
Removes TEST_HAS_CLASS_NTTP-guarded blocks; adds constexpr C-array and cuda::std::array fixtures; validates unwrap, traits, and bounds for direct __constant_sequence<int, 1, 2, 3> and __make_constant_sequence-built sequences; includes explicit empty-sequence bounds testing.

Assessment against linked issues

Objective Addressed Explanation
Change __constant_sequence from auto V NTTP to variadic template <class T, T... Vs> form [#9272]
Add __make_constant_sequence factory that accepts C-style array or cuda::std::array and expands elements into the value pack [#9272]
Enable C++17-compatible construction of constant sequences (remove class-NTTP requirement) [#9272]

Out-of-scope changes

None

Possibly related PRs

  • NVIDIA/cccl#9473: Changes __type_lowest/__type_highest, which the new empty-pack bounds paths use.

Suggested reviewers

  • gevtushenko
  • jrhemstad
  • miscco

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
libcudacxx/include/cuda/__argument/argument.h (1)

115-116: ⚡ Quick win

suggestion: These new non-public templates use short non-reserved parameter names (T, Vs, Is). Align them with libcudacxx internal naming rules (reserved identifiers with _ prefix, non-single-letter where possible) for consistency with this include path.
As per coding guidelines, "All non-public template parameters must be C++ reserved identifiers prefixed with _, avoiding single-letter names (e.g., use _Tp instead of _T)."

Also applies to: 152-153, 175-176, 688-689, 730-731, 802-803, 824-825, 894-895, 978-979, 1031-1032

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0879d251-db8c-482f-b2f3-61e4486be8df

📥 Commits

Reviewing files that changed from the base of the PR and between f52338f and 1001a74.

📒 Files selected for processing (4)
  • libcudacxx/include/cuda/__argument/argument.h
  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp

Comment thread libcudacxx/include/cuda/__argument/argument.h Outdated
Comment thread libcudacxx/include/cuda/__argument/argument.h Outdated
Comment thread libcudacxx/include/cuda/__argument/argument.h Outdated
Comment on lines +124 to +150
template <class T>
struct __is_builtin_array : ::cuda::std::false_type
{};

template <class T, ::cuda::std::size_t N>
struct __is_builtin_array<T[N]> : ::cuda::std::true_type
{};

template <class T>
struct __is_cuda_array : ::cuda::std::false_type
{};

template <class T, ::cuda::std::size_t N>
struct __is_cuda_array<::cuda::std::array<T, N>> : ::cuda::std::true_type
{};

template <class T>
struct __array_extent;

template <class T, ::cuda::std::size_t N>
struct __array_extent<T[N]> : ::cuda::std::integral_constant<::cuda::std::size_t, N>{};

template <class T, ::cuda::std::size_t N>
struct __array_extent<::cuda::std::array<T, N>> : ::cuda::std::integral_constant<::cuda::std::size_t, N>{};

template <class>
inline constexpr bool __always_false_v = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: All this already exists and we should just reuse the existing traits

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review.
I replaced them with the existing traits.

Comment on lines +132 to +133
template <class T>
struct __is_cuda_array : ::cuda::std::false_type

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: Internal traits should never go through structs, but use inline variables. We also have this already defined __is_cuda_std_array_v

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced

{};

template <class T, ::cuda::std::size_t N>
struct __is_builtin_array<T[N]> : ::cuda::std::true_type

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: is_bounded_array_v

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced

@github-project-automation github-project-automation Bot moved this from In Review to In Progress in CCCL Jun 22, 2026
};

template <class>
inline constexpr bool __always_false_v = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use cuda::std::__always_false_v instead.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

template <class>
inline constexpr bool __always_false_v = false;

template <const auto& Arr, ::cuda::std::size_t... Is>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Template parameters must be made __ugly as well

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

template <const auto& Arr, ::cuda::std::size_t... Is>
_CCCL_API constexpr auto __make_constant_sequence_impl(::cuda::std::index_sequence<Is...>)
{
using raw_array = ::cuda::std::remove_const_t<::cuda::std::remove_reference_t<decltype(Arr)>>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using raw_array = ::cuda::std::remove_const_t<::cuda::std::remove_reference_t<decltype(Arr)>>;
using __raw_array = ::cuda::std::remove_cvref_t<decltype(Arr)>;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion applied.

}
return __min;
}
return static_cast<_ElementType>(*::cuda::std::min_element(__first, __last));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no longer min_element?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review!

I think at one point during development I wasn't able to use it and replaced it here.
I found a way to use it again here making the code simpler.

Applied the same for the max computation too.

@codingwithmagga

Copy link
Copy Markdown
Author

@miscco @Jacobfaib

I have one additional question:

During development I tried to run the tests where I did the changes (e.g. argument_traits.pass.cpp) but I couldn't figure out which cmake target includes these test file.
Can you tell me how to run these tests (automatically)?

@miscco

miscco commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

@miscco @Jacobfaib

I have one additional question:

During development I tried to run the tests where I did the changes (e.g. argument_traits.pass.cpp) but I couldn't figure out which cmake target includes these test file. Can you tell me how to run these tests (automatically)?

libcu++ uses the LLVM Infrastructure Tester short lit

After you configured libcu++ you can directly invoke lit from the build/latest/libcudacxx folder with the relative path of the test / folder you want to test against. Please have a look here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[BUG]: constant_sequence can't take an array in C++17

3 participants