Skip to content

Complete VLA range and initializer-list assignment - #238

Merged
thirtytwobits merged 3 commits into
mainfrom
codex/issue-55-vla-assign
Oct 17, 2026
Merged

thirtytwobits merged 3 commits into
mainfrom
codex/issue-55-vla-assign

Conversation

@thirtytwobits

Copy link
Copy Markdown
Member

VLA only provided assign(count, value). Add assign(first, last) and assign(std::initializer_list<T>) for both ordinary elements and packed bool, completing the overloads requested in #55.

Single-pass input ranges reuse existing elements and grow incrementally. Forward ranges are measured first and obtain replacement storage in one allocation, without requiring old elements to be movable. Both paths preserve the allocator and maximum size, support proxy and move iterators, and maintain valid object lifetimes after failure. The API documentation describes partial updates, size limits, and allocation failure with exceptions disabled.

Validation:

  • Linux/GCC C++14: 467 tests passed across eight VLA suites; 109 passed in four embedded-profile suites with exceptions and RTTI disabled.
  • Clang C++14: VLA suites and the new assignment tests passed with exceptions enabled and disabled.
  • Clang C++20 with ASan/UBSan: 133 tests passed across assignment, exception safety, bool, and compatibility suites.
  • Formatting checked with the CI Toolshed image; git diff --check passed.

Regression coverage includes single-pass and forward iterators, initializer lists, integral overload resolution, empty ranges, packed-bit boundaries, move-only and immovable elements, allocation failure, and throwing iterator/element/allocator operations.

Closes #55.

@thirtytwobits
thirtytwobits marked this pull request as ready for review October 17, 2026 14:55
- Skip deallocate(nullptr, 0) for arrays that never allocated.
- Keep caller-requested element conversions from raising -Wconversion in
  the header; use std::copy_n for random-access prefixes.
- Enforce max_size() in ensure_size_plus_one() and resize() so spare
  capacity adopted by assignment cannot exceed the bound; drop the input
  path's special case and always trim the unused suffix.
- Guard loop increments against overloaded comma operators.
- Clamp VLA<bool>::resize() to existing storage when growth is declined
  without exceptions (heap overflow).
- Make assign(count, value) release insufficient storage before
  allocating, like the range overloads.
- Constrain the range constructors to input iterators and implement them
  with assign(first, last).
- Pack bits per byte in the VLA<bool> forward path; destroy suffixes with
  fast_destroy.
- Correct the assign documentation on failure detection and modes.
- Strengthen length_error and single-pass failure tests, add regression
  tests, and extend the fuzz harness to the new assign overloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

Range construction now rejects previously supported copy-constructible, nonassignable element types.

1 open issue
What changed in this PR

Completes VLA assignment overloads requested in #55 for ordinary elements and packed bool.

Changes:

  • Adds iterator-range and initializer-list assignment.
  • Updates storage replacement, size limits, and failure handling.
  • Adds assignment tests, exception-safety checks, and fuzz coverage.
File Description
include/​cetl/​variable_length_array.hpp Implements assignment overloads and updates range construction.
cetlvast/​suites/​unittest/​test_variable_length_array_exception_safety.cpp Tests assignment failures and lifetime preservation.
cetlvast/​suites/​unittest/​test_variable_length_array_assign.cpp Adds assignment and iterator regression tests.
cetlvast/​suites/​unittest/​CMakeLists.txt Registers the assignment test suite.
cetlvast/​suites/​fuzz/​fuzz_variable_length_array.cpp Exercises assignment variants against vector models.

Review effort: Balanced

Comment thread include/cetl/variable_length_array.hpp Outdated
MAMONTBOT
MAMONTBOT previously approved these changes Oct 17, 2026

@MAMONTBOT MAMONTBOT left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed the changes; no blocking issues found.

Range construction delegated to assign(first, last), whose forward path
instantiates element assignment even when nothing overlaps. Copy-
constructible types with deleted assignment, which main and std::vector
accept, stopped compiling. Give the constructors a construction-only path
(emplace_back for single-pass ranges; one allocation plus element
construction for forward ranges) that keeps the new iterator support,
max_size handling, and failure cleanup, and add a regression test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

No unresolved defects were identified in the implementation or its regression coverage.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@MAMONTBOT MAMONTBOT left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed the changes; no blocking issues found.

@thirtytwobits
thirtytwobits merged commit 4684da8 into main Oct 17, 2026
29 checks passed
@thirtytwobits
thirtytwobits deleted the codex/issue-55-vla-assign branch October 17, 2026 20:14
thirtytwobits added a commit that referenced this pull request Oct 17, 2026
…239)

Makes the full CETLVaSt suite build and pass with GCC 7 (7.5.0), and
adds GCC 7 to CI. The Arduino ecosystem is still on GCC 7, so this is a
step toward embedded/Arduino support. Refs #149, refs #136.

## Changes

**Library**
- `type_traits_ext.hpp` (#136): `is_convertible_without_narrowing` is
now spelled as copy-list-initialization of a by-value function
parameter. GCC 7 rejects the old `std::array<To, 1>{{{from}}}` for
scalar `To`. GCC 7 doesn't diagnose narrowing in constructor arguments
during list-initialization of a class type, so for that case it now
behaves like `std::variant`. The trait docs and
`test_type_traits_ext.cpp` describe this. This commit (0ad3b87) is the
fix that was sitting uncommitted on the `issue/136` working tree. If
#136 lands separately, drop it.
- `pf20/span.hpp`: the `CDE_span_002` debug assert now casts the
iterator distance to `size_type` explicitly before comparing it with
`Extent`. The comparison already did this conversion implicitly, so
behaviour is the same on every compiler. GCC 7 flags the implicit
version with `-Wsign-conversion` (Debug builds only).

**Tests only**
- `test_variable_length_array_exception_safety.cpp`: GCC 7 deduces
`const auto list = {Value{...}, ...}` as `std::initializer_list<const
Value>` (GCC PR c++/63149, fixed in GCC 8), so no constructor matched.
`VariableLengthArray` itself is correct. The fix is to spell out
`std::initializer_list<Value>`, both in the constructor test and in the
initializer-list assignment test that #238 added.
- `pmr/test_pmr_function.cpp`: clear functions with `= nullptr` instead
of `= {}`. Both resolve to `operator=(std::nullptr_t)`, but GCC 7
reports the `{}` form under `-Wzero-as-null-pointer-constant`.

**CI**
- `.github/workflows/cetlvast.yml`: adds a `gcc7-native` / `cpp-14`
entry to the arm64 verification matrix through `include:`, so GCC 7
isn't combined with cpp-17/20. It uploads the same artifacts as the
other entries. The `gcc7-native` presets only exist for cpp-14.

## Verification
Rebased onto main after #238 and re-verified:
- `cmake --workflow --preset workflow-gcc7-native-cpp-14-offline` passes
end to end in `ghcr.io/opencyphal/toolshed:ts24.4.3` (aarch64) from a
clean build dir. All 5 steps pass, including `run_unittests` and
`run_examples` in Release, ReleaseEP, Debug and DebugEP: 216 passing
suite runs.
- Host `workflow-gcc-native-cpp-14-offline` (Homebrew GCC 13.4, macOS)
passes end to end, also 216 passing suite runs. Clang and the other
standards are left to CI.
- Changed lines pass the toolshed's clang-format (`clang-format-diff`
with clang-format 19.1.7).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
thirtytwobits added a commit that referenced this pull request Oct 18, 2026
Adds `operator=(std::initializer_list)` to `cetl::VariableLengthArray`,
matching [`std::vector::operator=`
(3)](https://en.cppreference.com/w/cpp/container/vector/operator%3D).

Both the general and the packed-`bool` specializations forward to
`assign(std::initializer_list)` (from #238), so the operator has the
same guarantees as that overload:

- the allocator and `max_size()` are kept, and existing storage is
reused when it is large enough
- a list longer than `max_size()` throws `std::length_error`; with
exceptions disabled the list is truncated to `max_size()`
- allocation failure throws `std::bad_alloc`
- returns `*this`

`vla = {}` now resolves to the new overload and clears the array, the
same as `std::vector`.

## Tests
New cases in `test_variable_length_array_assign.cpp`, typed over `int`
and `bool`:
- growing, shrinking, clearing, and re-growing across packed-byte
boundaries, checked against `std::vector`
- the returned reference
- the logical maximum, with and without exceptions
- reusing storage without allocating, and keeping the allocator and
`max_size()`

## Validation
- GCC 13, C++14: all 11 VLA test suites pass in Debug and DebugEP
(`-fno-exceptions`)
- Clang, C++14 and C++20, with and without exceptions: the assign suite
compiles cleanly with `-Wall -Wextra -Werror -Wconversion
-Wsign-conversion`
- `clang-format` 19.1.7 from `toolshed:ts24.4.3` (the CI image) reports
no changes for either file; `git diff --check` is clean

Closes #70.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add assign() to VLA

3 participants