Add constrained span(initializer_list) constructor#8314
Merged
miscco merged 23 commits intoNVIDIA:mainfrom Apr 8, 2026
Merged
Conversation
Re-add the span(initializer_list) constructor that P4144R1 removed from C++26. Uses Hana Dusikova's fix: constrain with same_as<value_type> to prevent narrowing and is_const_v<element_type> to prevent dangling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…guide Move #include <cuda/std/initializer_list> to the top-level header group (alongside array, cstddef, version) per project include ordering convention. Add CTAD deduction guide: span(initializer_list<T>) -> span<const T>. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests cover dynamic/static extent construction, explicit initializer_list variables, empty lists, value integrity, bool literals, const volatile element types, and CTAD deduction. Both constexpr and runtime paths verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test dynamic/static extent construction, explicit initializer_list variable, empty lists, value integrity, bool literals, const volatile element type, and CTAD deduction guide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that the constrained span(initializer_list) constructor correctly rejects non-const element types and type-mismatched initializer lists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The span constructed from a temporary braced-init-list dangles after the initializer_list temporary is destroyed. Use named variables so the backing storage outlives element access through the span. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- const volatile: only check size (volatile reads are not constexpr, and volatile int has no operator== with int) - CTAD: use parentheses initialization to avoid brace-init ambiguity Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The libcudacxx lit config only supports .pass.cpp, .fail.cpp, .runfail.cpp, and .sh.cpp suffixes. Rename to .fail.cpp format. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The deduction guide span(initializer_list<T>) -> span<const T> causes
C++ to prefer the initializer_list interpretation for braced-init-list
CTAD, breaking existing span s{ptr, ptr} deduction (deduces
span<const int*> instead of span<int>). Remove the guide; the
constrained constructor works fine with explicit types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
- Remove redundant type instantiations (long, double) that test the same code path as int - Remove redundant narrowing case (const short, same as const bool) - Add span<int* const> positive test (is_const_v is true for const ptr) - Add span<const int*> negative test (is_const_v is false — the pointer itself is not const, only the pointee is) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mhoemmen
reviewed
Apr 7, 2026
mhoemmen
reviewed
Apr 7, 2026
mhoemmen
reviewed
Apr 7, 2026
mhoemmen
reviewed
Apr 7, 2026
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
…n.cons/initializer_list.pass.cpp Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
…n.cons/initializer_list.pass.cpp Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…lity MSVC 14.29 eagerly evaluates is_const_v<element_type> during class instantiation because element_type is a class template parameter. This causes a hard error instead of SFINAE discard. Adding a defaulted function template parameter _Ep = element_type makes the condition depend on the function's own template parameter, deferring evaluation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
miscco
approved these changes
Apr 8, 2026
Contributor
|
Thanks a lot @rparolin for addin the fix |
Co-authored-by: Michael Schellenberger Costa <miscco@nvidia.com>
Contributor
🥳 CI Workflow Results🟩 Finished in 2h 04m: Pass: 100%/108 | Total: 2d 23h | Max: 2h 03m | Hits: 79%/281680See results here. |
jainishmehta
pushed a commit
to jainishmehta/cccl
that referenced
this pull request
Apr 19, 2026
* feat: add constrained span(initializer_list) constructor
Re-add the span(initializer_list) constructor that P4144R1 removed from
C++26. Uses Hana Dusikova's fix: constrain with same_as<value_type> to
prevent narrowing and is_const_v<element_type> to prevent dangling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move initializer_list include to top-level group, add deduction guide
Move #include <cuda/std/initializer_list> to the top-level header group
(alongside array, cstddef, version) per project include ordering convention.
Add CTAD deduction guide: span(initializer_list<T>) -> span<const T>.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add positive test cases for span(initializer_list) constructor
Tests cover dynamic/static extent construction, explicit initializer_list
variables, empty lists, value integrity, bool literals, const volatile
element types, and CTAD deduction. Both constexpr and runtime paths verified.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add passing tests for span(initializer_list) constructor
Test dynamic/static extent construction, explicit initializer_list
variable, empty lists, value integrity, bool literals, const volatile
element type, and CTAD deduction guide.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add compile-failure tests for span(initializer_list) constructor
Verify that the constrained span(initializer_list) constructor correctly
rejects non-const element types and type-mismatched initializer lists.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: apply clang-format to initializer_list.verify.cpp
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use named initializer_list variables to avoid dangling in tests
The span constructed from a temporary braced-init-list dangles after the
initializer_list temporary is destroyed. Use named variables so the
backing storage outlives element access through the span.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fix const volatile and CTAD tests
- const volatile: only check size (volatile reads are not constexpr,
and volatile int has no operator== with int)
- CTAD: use parentheses initialization to avoid brace-init ambiguity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: replace .verify.cpp with .fail.cpp for negative tests
The libcudacxx lit config only supports .pass.cpp, .fail.cpp,
.runfail.cpp, and .sh.cpp suffixes. Rename to .fail.cpp format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove initializer_list deduction guide to avoid CTAD regression
The deduction guide span(initializer_list<T>) -> span<const T> causes
C++ to prefer the initializer_list interpretation for braced-init-list
CTAD, breaking existing span s{ptr, ptr} deduction (deduces
span<const int*> instead of span<int>). Remove the guide; the
constrained constructor works fine with explicit types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove extra blank line, add dangling comments to size-only tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: improve deviation comment to explain why const is redundant
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: audit and refine initializer_list tests
- Remove redundant type instantiations (long, double) that test the
same code path as int
- Remove redundant narrowing case (const short, same as const bool)
- Add span<int* const> positive test (is_const_v is true for const ptr)
- Add span<const int*> negative test (is_const_v is false — the pointer
itself is not const, only the pointee is)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: replace magic numbers with il.size() in size assertions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: fix remaining magic numbers in initializer_list variable tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: apply clang-format alignment
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update libcudacxx/include/cuda/std/span
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
* Update libcudacxx/test/libcudacxx/std/containers/views/views.span/span.cons/initializer_list.pass.cpp
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
* Update libcudacxx/include/cuda/std/span
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
* Update libcudacxx/test/libcudacxx/std/containers/views/views.span/span.cons/initializer_list.pass.cpp
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
* fix: add defaulted _Ep template param for MSVC 14.29 SFINAE compatibility
MSVC 14.29 eagerly evaluates is_const_v<element_type> during class
instantiation because element_type is a class template parameter. This
causes a hard error instead of SFINAE discard. Adding a defaulted
function template parameter _Ep = element_type makes the condition
depend on the function's own template parameter, deferring evaluation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: apply clang-format
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update libcudacxx/include/cuda/std/span
Co-authored-by: Michael Schellenberger Costa <miscco@nvidia.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mark Hoemmen <mhoemmen@users.noreply.github.com>
Co-authored-by: Michael Schellenberger Costa <miscco@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
span(initializer_list)constructor that P4144R1 removed from C++26, using Hana Dusíková's constrained fixsame_as<value_type>(prevents narrowing) andis_const_v<element_type>(prevents dangling)span s{ptr, ptr})Motivation
This implementation supports a WG21 paper proposing to restore the
span(initializer_list)constructor with safety constraints. Having a working implementation in libcu++ strengthens the paper with real-world evidence.Key design decisions
initializer_list<_InitListValueType>instead of Hana's originalinitializer_list<const _InitListValueType>— theconstis redundant becauseinitializer_list<T>::begin()already returnsconst T*, and omitting it simplifies SFINAE fallback deductionspan(initializer_list<T>) -> span<const T>causes C++ to prefer theinitializer_listinterpretation for all braced-init-list CTAD, breaking existingspan s{ptr, sentinel}deductionTest plan
initializer_list.pass.cpp— dynamic/static extent, named variables, empty lists, value integrity, bool literals, const volatileinitializer_list.fail.cpp— non-const element type, narrowing (int→bool, int→short, double→int)🤖 Generated with Claude Code