VectorPro
High-performance, header-only dynamic array with configurable growth policy, custom allocator support, and optional modification-event notifications.
Loading...
Searching...
No Matches

VectorPro

Version License - MIT C++ - 20

CI / CD

Build and Test Benchmarks Packaging Release

Code Quality & Safety

Coverage Sanitizers Clang Tidy Clang Format CodeQL Fuzzing OpenSSF Best Practices

Documentation

Documentation

Compiler Support

GCC - support Clang - support MSVC - support AppleClang - 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.


📑 Table of Contents

  • Features
  • Requirements
  • Installation
  • Quick Start
  • Project Structure
  • Development
  • Benchmarks
  • Fuzzing
  • Documentation
  • Contributing
  • Changelog
  • Security
  • License


<a id="features"></a>✨ Features

  • Configurable growth policy — capacity growth is a compile-time 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.
  • Aliasing-safe 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.
  • Zero-overhead optional event system — 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.
  • Full custom allocator support — built on 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.
  • A real 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().
  • Exception-safe reallocation and copy paths — 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.
Back to top

<a id="requirements"></a>📋 Requirements

  • A C++20-conformant compiler (tested: GCC, Clang, MSVC, AppleClang)
  • CMake 3.20+
Back to top

<a id="installation"></a>📦 Installation

From source:

git clone https://github.com/privateMwb/VectorPro.git
cd VectorPro
cmake -B build \
-DBUILD_TESTS=OFF \
-DBUILD_BENCHMARKS=OFF \
-DBUILD_REGRESSION=OFF \
-DBUILD_EXAMPLES=OFF
cmake --install build

Then, in your own CMakeLists.txt:

find_package(VectorPro CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE VectorPro::VectorPro)

‍vcpkg and Conan packages are built and verified (recipe in packaging/recipes/vectorpro/, port in packaging/vcpkg/ports/vectorpro/), but not yet published to the public registries. This section will be updated once they are.

Back to top

<a id="quick-start"></a>🚀 Quick Start

int main() {
values.push_back(1);
values.push_back(2);
values.emplace_back(3);
for (int v : values) {
// range-for works via begin()/end(), backed by a real
// std::contiguous_iterator
}
values.insert(values.begin(), 0); // {0, 1, 2, 3}
values.erase(values.begin()); // {1, 2, 3}
}
A dynamically resizable contiguous array.
Definition Vector.h:97
void push_back(const T &value)
Appends a copy of value to the end, growing capacity if needed.
iterator insert(const_iterator pos, const T &value)
Inserts a copy of value before pos.
void emplace_back(Args &&... args)
Constructs a new element in place at the end of the vector.
iterator begin() noexcept
Returns an iterator to the first element.
iterator erase(const_iterator pos)
Erases the element at pos.

Subscribing to modification events (requires ObservableVector):

auto handle = values.subscribe([](const auto& v, auto event) {
std::cout << "size " << event.oldSize << " -> " << event.newSize << '\n';
});
values.push_back(42); // triggers the listener
values.unsubscribe(handle);
void unsubscribe(ListenerHandle handle)
Removes a previously registered listener.
&&Listener< F, Vector< T, Allocator, GrowthNum, GrowthDen, EnableEvents > > ListenerHandle subscribe(F &&listeners)
Registers a listener to be notified of modification events.

A custom growth policy and bounds-checked access:

VectorPro::Vector<int, std::allocator<int>, /*GrowthNum=*/3, /*GrowthDen=*/2> values;
try {
values.at(100); // out of range on an empty vector
} catch (const std::out_of_range& e) {
std::cerr << e.what() << '\n';
}
reference at(std::size_t index)
Returns a reference to the element at index, with bounds checking.
Back to top

<a id="project-structure"></a>🗂️ Project Structure

VectorPro/
├── include/
│ └── VectorPro/
│ ├── Vector.h
│ ├── Vector.tpp
│ └── Iterator.h
│
├── tests/
│ ├── custom/
│ ├── google/
│ ├── CMakeLists.txt
│ └── README.md
│
├── benchmarks/
│ ├── baselines/
│ ├── custom/
│ ├── google/
│ ├── result/
│ ├── CMakeLists.txt
│ └── README.md
│
├── examples/
│ ├── support/
│ ├── suite/
│ ├── example_main.cpp
│ ├── CMakeLists.txt
│ └── README.md
│
├── regression/
│ ├── custom/
│ ├── google/
│ ├── results/
│ ├── CMakeLists.txt
│ └── README.md
│
├── fuzz/
│ └── fuzz_vector.cpp
│
├── .clusterfuzzlite/
│ ├── Dockerfile
│ ├── build.sh
│ └── project.yaml
│
├── packaging/
│ ├── README.md
│ ├── requirements.in
│ ├── requirements.txt
│ ├── recipes/
│ ├── vcpkg/
│ └── vcpkg-smoke-test/
│
├── scripts/
│ └── update_package_files.py
│
├── .github/
│ ├── assets/
│ ├── releases/
│ ├── workflows/
│ ├── CODEOWNERS
│ └── dependabot.yml
│
├── cmake/
│ └── VectorProConfig.cmake.in
│
├── docs/
│ ├── Doxyfile
│ └── README.md
│
├── .clang-format
├── .clang-tidy
├── .gitignore
├── CMakeLists.txt
├── README.md
├── CONTRIBUTING.md
├── CHANGELOG.md
├── SECURITY.md
├── FUZZING.md
└── LICENSE
Back to top

<a id="development"></a>🛠️ Development

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):

cmake -B build
cmake --build build

Run the test suite:

ctest --test-dir build

Run benchmarks and check for regressions:

./build/benchmarks
./build/regression # latest baseline vs. benchmarks/results/benchmark_results.json
./build/regression v1.2.0 # a specific baseline vs. current
./build/regression v1.2.0 v1.4.0 # two baselines against each other

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.

Back to top

<a id="benchmarks"></a>📊 Benchmarks

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.

Back to top

<a id="fuzzing"></a>🐛 Fuzzing

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.

Back to top

<a id="documentation"></a>📖 Documentation

Full API reference, generated with Doxygen from docs/Doxyfile:

https://privateMwb.github.io/VectorPro/

Back to top

<a id="contributing"></a>🤝 Contributing

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:

  • Run the test suite (ctest --test-dir build)
  • If you're changing a hot path, run ./build/regression and mention the results in your PR description
Back to top

<a id="changelog"></a>📝 Changelog

See CHANGELOG.md for a curated, per-release summary of changes, or the Releases page for the full release notes.

Back to top

<a id="security"></a>🔒 Security

See SECURITY.md for the supported versions, how to report a vulnerability (including privately, via GitHub Security Advisories), and the disclosure timeline.

Back to top

<a id="license"></a>📄 License

MIT — see [LICENSE](LICENSE) for details.

Built with C++20

Back to top