|
VectorPro
High-performance, header-only dynamic array with configurable growth policy, custom allocator support, and optional modification-event notifications.
|
CI / CD
Code Quality & Safety
Documentation
Compiler Support
VectorPro is a header-only, std::vector-like dynamic array for modern C++ — a configurable growth policy, full custom-allocator support, a real std::contiguous_iterator, and optional zero-overhead modification-event notifications, so you only pay for the parts you actually use.
GrowthNum/GrowthDen ratio (defaults to 2/1, i.e. doubling), not a hardcoded factor. growCapacity() saturates at SIZE_MAX instead of overflowing, and always guarantees strict growth even for tight ratios.push_back()/insert() — safe to pass a reference into the vector itself (v.push_back(v[i])). The element's offset is snapshotted before any reallocation or shift that could invalidate it, instead of leaving that as undefined behavior for the caller to avoid.subscribe()/unsubscribe() are only available on the ObservableVector alias. A plain Vector with events disabled carries no listener storage at all ([[no_unique_address]]) and compiles away every notification call site (if constexpr in notify()), rather than paying a runtime check per modification.std::allocator_traits, honoring propagate_on_container_copy_assignment, propagate_on_container_move_assignment, and select_on_container_copy_construction rather than assuming the default allocator's behavior.std::contiguous_iterator — not a raw pointer typedef. Supports the full random-access iterator interface, implicit iterator → const_iterator conversion, and zero-copy std::span views via as_span().reallocate(), copyBufferFrom(), and the copy-and-swap fallback in operator=() all roll back cleanly on a throwing constructor, leaving the vector exactly as it was before the call.From source:
Then, in your own CMakeLists.txt:
vcpkg and Conan packages are built and verified (recipe in
packaging/recipes/vectorpro/, port inpackaging/vcpkg/ports/vectorpro/), but not yet published to the public registries. This section will be updated once they are.
Subscribing to modification events (requires ObservableVector):
A custom growth policy and bounds-checked access:
The from-source install above builds the library only. To work on VectorPro itself — running tests, benchmarks, or the regression tool — build with everything enabled (the default):
Run the test suite:
Run benchmarks and check for regressions:
regression picks the latest baseline by semantic version (v1.10.0 correctly outranks v1.9.0), not alphabetical filename order, and auto-names its output (regression_v1.2.0_vs_current.md/.json, etc.).
See packaging/README.md for notes on verifying the vcpkg port and Conan recipe locally.
Measured against std::vector, same build, at 10K / 100K / 1M iterations (benchmarks/baselines/v1.0.0.json has the full dataset).
Environment: 4-core CI runner @ 3.26 GHz, 32 KiB L1 / 512 KiB L2 / 32 MiB L3, Release build — see the context block in benchmarks/baselines/gv1.0.0.json for the exact machine and library version each run was captured on.
| Operation | VectorPro (1M) | std::vector (1M) | Δ |
|---|---|---|---|
Pop Back() | 63.81 ms | 577.46 ms | +804.9% |
Erase() end | 51.33 ms | 298.78 ms | +482.0% |
Clear() | 63.59 ms | 307.65 ms | +383.8% |
Move-construct | 13.63 ms | 38.59 ms | +183.2% |
| Growth reallocation | 145.45 ms | 386.37 ms | +165.6% |
Erase() middle | 68.23 ms | 175.62 ms | +157.4% |
Move-assign | 16.63 ms | 38.56 ms | +131.9% |
Insert() end | 118.56 ms | 230.92 ms | +94.8% |
Front()/Back() | 300.87 us | 508.17 us | +68.9% |
Reserve() no-op (10K) | 5.55 us | 2.75 us | -50.4% |
| Erase-Remove If | 1.31 s | 775.74 ms | -40.8% |
VectorPro's largest wins show up on removal and reallocation-heavy workloads at the 1M scale — pop_back(), erase() (front/middle/end), clear(), and growth-driven reallocation all pull well ahead of std::vector as element count grows, and the same holds for move construction and move assignment.
The trade-off is concentrated in two spots: remove_if()'s compaction loop runs behind std::vector's erase-remove idiom at every scale tested, and reserve()'s no-op check carries a small fixed branch overhead that only shows up at the smallest (10K) iteration count.
Vector<int> is continuously fuzzed via ClusterFuzzLite: differential testing against a std::vector<int> shadow model, under AddressSanitizer and UndefinedBehaviorSanitizer. A short pass runs on every PR touching Vector's implementation; a longer pass runs nightly.
This covers growth/reallocation correctness, the aliasing-safe push_back/insert path, at()'s bounds-checking contract, and both operator= overloads including self-assignment — deliberately targeting the class's highest-complexity, un-refactored functions (see FUZZING.md for why they weren't refactored, and how this harness stands in for that instead). Custom allocators, the observer/event-notification system, and exception-injection during copy construction/assignment aren't covered yet — see FUZZING.md for full scope, running locally, and reproducing a failing input.
Full API reference, generated with Doxygen from docs/Doxyfile:
https://privateMwb.github.io/VectorPro/
Issues and pull requests are welcome — see CONTRIBUTING.md for the full process, coding standard reference, and what CI checks on every PR. Short version, before submitting:
ctest --test-dir build)./build/regression and mention the results in your PR descriptionSee CHANGELOG.md for a curated, per-release summary of changes, or the Releases page for the full release notes.
See SECURITY.md for the supported versions, how to report a vulnerability (including privately, via GitHub Security Advisories), and the disclosure timeline.
MIT — see [LICENSE](LICENSE) for details.
Built with C++20