Skip to content

[libcu++] Indirect indirect_binary invocable#9417

Open
miscco wants to merge 1 commit into
NVIDIA:mainfrom
miscco:indirect_binary_invocable
Open

[libcu++] Indirect indirect_binary invocable#9417
miscco wants to merge 1 commit into
NVIDIA:mainfrom
miscco:indirect_binary_invocable

Conversation

@miscco

@miscco miscco commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

The standard currently does only know indirectly_unary_invocable. However, there are a lot of algorithms like adjacent_difference where we want to make sure that we can invoke a functor by dereferencing two iterators.

Add this as an extension

@miscco miscco requested review from a team as code owners June 12, 2026 09:16
@miscco miscco requested a review from griwes June 12, 2026 09:16
@miscco miscco requested a review from srinivasyadav18 June 12, 2026 09:16
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jun 12, 2026
@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Jun 12, 2026
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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 pull request introduces indirectly_binary_invocable and indirectly_regular_binary_invocable concepts to libcu++, extending the iterator indirect-callability concept family. These new concepts enable checking whether a callable can be invoked with dereferenced pairs of iterators, filling a gap in the C++ standard library's concept definitions. This addresses requirements for algorithms like adjacent_difference that operate on pairs of elements.

Changes

Core Implementation

libcudacxx/include/cuda/std/__iterator/concepts.h

Added two new iterator indirect-callability concepts:

  • indirectly_binary_invocable<_Fp, _It1, _It2>: Validates that a callable can be invoked with combinations of dereferenced iterator pairs
  • indirectly_regular_binary_invocable<_Fp, _It1, _It2>: Similar to above, with regular invocation semantics

Both concepts require:

  • Both iterators to be indirectly_readable
  • The function object to be copy_constructible
  • Comprehensive invocable/regular_invocable checks across combinations of iter_value_t, iter_reference_t, and iter_common_reference_t
  • common_reference_with constraints linking invocation results across value/reference/cv variants

Implementation integrates with existing iterator concepts and predicates (matching the project's concept/macro fallbacks where applicable).

Test Coverage

libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_binary_invocable.compile.pass.cpp

Comprehensive compile-time validation featuring:

  • GoodInvocable functor with overloads covering all required argument combinations
  • 11 intentionally non-conforming invocables testing specific failure modes: iterator readability (gated by TEST_STD_VER), copy-constructibility, missing call expressions for value/reference/common-reference variants, and incompatible return-type common-reference relationships
  • Additional tests for function pointer and function reference callables and several negative callable forms
  • A trivial main returning 0

libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_binary_invocable.compile.pass.cpp

Mirrors the binary invocable test structure with regular invocation semantics, validating both positive and negative cases for indirectly_regular_binary_invocable using equivalent test patterns and coverage.

Test Support

libcudacxx/test/support/indirectly_readable.h

Added IndirectlyReadable2<Token> template struct to support testing with pairs of distinct indirectly-readable iterators, mirroring the existing IndirectlyReadable<Token> pattern and providing common-reference test types used by the new tests.

Impact

  • New concepts and tests are additive and confined to iterator concept machinery and test-support utilities.
  • Lines added across implementation and tests: +~619 (implementation + tests + support), no deletions reported.
  • Estimated review effort: Medium–High due to concept complexity and comprehensive negative-case coverage.

Walkthrough

suggestion: PR adds two binary iterator invocable concepts with parallel macro-based fallbacks, compile-pass tests for both positive and negative cases, and a small test-support helper for indirectly readable iterators.

Changes

Binary invocable concepts

Layer / File(s) Summary
Binary invocable concept definitions
libcudacxx/include/cuda/std/__iterator/concepts.h
Introduces indirectly_binary_invocable and indirectly_regular_binary_invocable concepts requiring both input iterators to be indirectly_readable, the function object to be copy_constructible, with invocable/regular_invocable checks across value/reference/common-reference forms and common_reference_with constraints on invoke_result_t variants. Provides both _CCCL_HAS_CONCEPTS and _CCCL_CONCEPT macro implementations.
Binary invocable compile-pass tests
libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_binary_invocable.compile.pass.cpp
Validates indirectly_binary_invocable with positive static_assert for GoodInvocable and negative static_asserts covering iterator non-readability, deleted copy constructor, missing/deleted call operators for specific argument form combinations, and lack of common-reference among return types.
Regular binary invocable compile-pass tests
libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_binary_invocable.compile.pass.cpp
Validates indirectly_regular_binary_invocable with positive static_assert for GoodInvocable and negative static_asserts for the same constraint classes as the binary variant, including function-pointer and reference-callable cases.
Test support infrastructure
libcudacxx/test/support/indirectly_readable.h
Added IndirectlyReadable2 template struct defining value_type and operator*() return type for binary iterator concept testing.

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

coderabbitai[bot]

This comment was marked as outdated.

@miscco miscco force-pushed the indirect_binary_invocable branch from c92d1d8 to 82af814 Compare June 12, 2026 09:28
@github-actions

This comment has been minimized.

The standard currently does only know `indirectly_unary_invocable`. However, there are a lot of algorithms like `adjacent_difference` where we want to make sure that we can invoke a functor by dereferencing two iterators.

Add this as an extension
@miscco miscco force-pushed the indirect_binary_invocable branch from 82af814 to 4171c33 Compare June 12, 2026 15:31

@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.

🧹 Nitpick comments (1)
libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_binary_invocable.compile.pass.cpp (1)

37-43: ⚡ Quick win

suggestion: Add the symmetric unreadable-I2 negative assertion here. indirectly_binary_invocable requires both iterator operands to satisfy indirectly_readable, but this file only proves the failure when I1 is unreadable. A typo in either implementation path that re-checks I1 and forgets I2 would still pass this test. As per coding guidelines, libcudacxx/**/* reviews should focus on correctness, standard-library conformance, tests, and portability across supported CUDA toolchains.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 99343c8f-2a76-4650-bc9f-ad9cd070c81d

📥 Commits

Reviewing files that changed from the base of the PR and between 82af814 and 4171c33.

📒 Files selected for processing (4)
  • libcudacxx/include/cuda/std/__iterator/concepts.h
  • libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_binary_invocable.compile.pass.cpp
  • libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_binary_invocable.compile.pass.cpp
  • libcudacxx/test/support/indirectly_readable.h
🚧 Files skipped from review as they are similar to previous changes (3)
  • libcudacxx/test/support/indirectly_readable.h
  • libcudacxx/include/cuda/std/__iterator/concepts.h
  • libcudacxx/test/libcudacxx/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_binary_invocable.compile.pass.cpp

@github-actions

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 35m: Pass: 100%/118 | Total: 2d 14h | Max: 1h 20m | Hits: 67%/530703

See results here.

_CCCL_CONCEPT indirectly_copyable_storable = _CCCL_FRAGMENT(__indirectly_copyable_storable_, _In, _Out);

template <class _Fp, class _It1, class _It2>
_CCCL_CONCEPT indirectly_binary_invocable = _CCCL_REQUIRES_EXPR((_Fp, _It1, _It2))(

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.

Can we just combine these into just the _CCCL_CONCEPT form instead of duplicating? This is a massive concept to write out twice.

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

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

2 participants