Skip to content

Avoid unnecessary container copies in non-mutating operations (#30)#35

Merged
jkalias merged 2 commits into
mainfrom
claude/open-issues-list-z2d0z7
Jun 15, 2026
Merged

Avoid unnecessary container copies in non-mutating operations (#30)#35
jkalias merged 2 commits into
mainfrom
claude/open-issues-list-z2d0z7

Conversation

@jkalias

@jkalias jkalias commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

Addresses #30 (performance). Eliminates unnecessary container copies in non-mutating operations, fixes an insert_back double-copy and a pessimizing move, and refreshes inline docs that became stale after the precondition change in #29. Pure optimization — no behavior change for valid usage.

1. Copy → move on non-mutating returns

Many non-mutating operations built a local std::vector/std::set/std::map, then passed it as an lvalue into a wrapper constructor that has both a copy and a move overload — so the lvalue selected the copy, duplicating the whole container needlessly. They now std::move the local into the wrapper:

  • vector: filtered / filtered_parallel, sorted / sorted_parallel, removing_at / removing_back / removing_range, inserting_at / inserting_back, replacing_range_at, map / map_parallel
  • set: difference_with / union_with / intersect_with, map, filtered, removing / inserting, zip_impl
  • map: removing / inserting / filtered

2. insert_back double-copy

vector::insert_back(T) / inserting_back(T) now push_back(std::move(value)) instead of copying the by-value sink parameter a second time.

3. Pessimizing move

set::keys() now return vec; instead of return std::move(vec); (the explicit move defeated NRVO; -Wpessimizing-move).

4. Docs refresh

After #29 made precondition checks always-on, four operator[] comments (vector + set) plus map's const operator[] still said "Bounds checking (assert) is enabled for debug builds." Updated them to state the checks run in both debug and release (std::abort) and to mention the FCPP_NO_PRECONDITION_CHECKS opt-out.

Tests

Added a counted test type that tracks copy- vs move-constructions, and tests that prove the optimization rather than just behavior:

  • VectorTest.NonMutatingReturnMovesInsteadOfCopiesremoving_back: 7 → 4 copies
  • SetTest.NonMutatingReturnMovesInsteadOfCopiesremoving: 6 → 3 copies
  • VectorTest.InsertBackMovesElementInsteadOfCopyingTwice — 2 copies/0 moves → 1 copy / 1 move

Each was verified to fail on the pre-fix code (with exactly the higher counts above) and pass after, under both C++11 and C++17.

Verification

Built and ran the full suite under Debug & Release × C++11 & C++17 — all green (305 tests C++17, 289 C++11).

Closes #30.

https://claude.ai/code/session_011y3XcVg3UCcgi5JMEo2tso

claude added 2 commits June 14, 2026 12:31
)

Move local containers into the returned wrapper instead of copying them.
Many non-mutating operations (filtered, sorted, removing_*, inserting_*,
replace/replacing_range, map, set difference/union/intersect/map/zip, and the
map removing/inserting/filtered helpers) built a local std::vector/std::set/
std::map and passed it as an lvalue into a wrapper constructor that has both a
copy and a move overload, selecting the copy. They now std::move the local.

Also:
- vector::insert_back(T) / inserting_back(T) now push_back(std::move(value))
  instead of copying the by-value parameter a second time.
- set::keys() returns the local directly instead of std::move(vec), which was
  a pessimizing move that defeated NRVO.

Docs: the operator[] / map const operator[] comments still claimed bounds
checking was "enabled for debug builds". After the precondition changes the
checks are always on (abort in debug and release); updated the comments and
mention FCPP_NO_PRECONDITION_CHECKS.
Introduce a `counted` test type that tracks copy- vs move-constructions, and
add tests proving the optimization rather than just behavior:

- VectorTest.NonMutatingReturnMovesInsteadOfCopies (removing_back)
- VectorTest.InsertBackMovesElementInsteadOfCopyingTwice
- SetTest.NonMutatingReturnMovesInsteadOfCopies (removing)

Each was verified to fail on the pre-fix code (extra container/element copies)
and pass after, under both C++11 and C++17.
@jkalias jkalias changed the title Claude/open issues list z2d0z7 Avoid unnecessary container copies in non-mutating operations (#30) Jun 14, 2026
@jkalias jkalias merged commit 3a5c2ea into main Jun 15, 2026
12 checks passed
@jkalias jkalias deleted the claude/open-issues-list-z2d0z7 branch June 15, 2026 11:29
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.

Performance: avoid unnecessary container copies in non-mutating returns and insert_back

2 participants