This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ea_data_structures is a header-only C++20 library of data structures, smart pointers, allocators, and utilities. Everything lives under the EA:: namespace. The library is also shaped to work as a JUCE module (see the BEGIN_JUCE_MODULE_DECLARATION block in ea_data_structures/ea_data_structures.h), which is why every feature is included through that single umbrella header.
The main CMake target is an INTERFACE library — there is nothing to compile on its own. Consumers link against ea_data_structures and include ea_data_structures/ea_data_structures.h:
add_subdirectory(path/to/cpp_data_structures)
target_link_libraries(my_target PRIVATE ea_data_structures)The INTERFACE target declares target_compile_features(... INTERFACE cxx_std_20), so consumers automatically get a C++20-or-higher requirement propagated onto anything that links it.
The Tests/ target and NanoTest fetch are only enabled when this repo is the top-level CMake project (PROJECT_IS_TOP_LEVEL). Consumers that add_subdirectory this repo as a dependency don't pay that cost.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureEach nano::test("Name") registers as an individual CTest entry, so you can run one test with ctest --test-dir build -R Vector.contains or directly via ./build/Tests/ea_data_structures_tests --test Vector.contains. --list-tests on the executable lists everything it registered.
The top-level build sets CMAKE_CXX_STANDARD 20 because NanoTest's own static libs don't declare a standard themselves. _clang-format and .clang-tidy at the repo root define the expected style and checks; run clang-format / clang-tidy against changed files before committing.
Everything user-facing is re-exported from ea_data_structures/ea_data_structures.h. When adding a new public header, add its #include there — otherwise JUCE-module consumers won't see it. The subdirectories group related concerns:
Structures/— containers (Vector,Array,MapVector,SmallVector,StaticVector,FixedDynamicArray,OwnedVector,MultiVector,CircularBuffer,Fifo,BufferView,CopyOnWrite,Filtered,SharedGUIData).SizeType.his the shared size alias.Pointers/— ownership and type-erasure primitives (OwningPointer,Ref,RefOrOwn,Any,AnyRef,Cloneable,CallbackFunc,DynamicFunc).Allocators/— allocator machinery backingSmallVector/StaticVector, plus a PMR wrapper andMultiPoolAllocator.Flags/— concurrency and atomic helpers (Locks,RecursiveSpinLock,CopyableAtomic,AtomicHelpers,Bool).ValueWrapper/—ValueandConstructed(in-place-optional-like object with no heap allocation).Utilities/— free-function helpers (VectorUtilities,MapUtilities,TupleUtilities,GenericUtilities,StaticObjects).
- Always run clang-format on every changed file.
- Use modern, RAII style.
intsize semantics, notsize_t. TheVector/Arraywrappers deliberately exposeint-based sizes and indices — do not "fix" this tosize_t. Helper methods (contains,eraseIf,addIfNotThere,sort, …) are the whole point of these wrappers over raw STL.size()asserts that the count fits anint;getSize()is the fullsize_t, for STL calls and for aSpanover more than anintdescribes, andSpanbuilds from a container'sgetSize()when it has one.Spanwrapsstd::spanthe wayVectorwrapsstd::vector—getSpan()besidegetVector()/getArray().Arrayis constexpr throughout. Every member except the twosortoverloads (std::sortonly becomes constexpr in C++26) is usable in a constant expression, as are theVectors::search and reverse helpers they delegate to (getIndexOf,getIndexIf,countIf,contains,find,findIf,reverse,rotate). That is what lets a type that stores anArray— a matrix, a lookup table — keep its own constexpr, so don't add a non-constexpr member without a reason. Accessors need const overloads for the same reason: aconstexprobject is a const one.- Real-time safety.
SharedGUIData/GUIToRealTime,Fifo,CircularBuffer, andFlags/types are designed for audio/real-time threads — preserve lock-free / allocation-free behavior when editing them. Atomic<T>(inFlags/) static-assertsTis always lock-free; keep that guarantee intact.- Formatting: Allman braces, 4-space indent, 85-column limit, left-aligned pointers,
SortIncludes: false(header order is intentional — notably inea_data_structures.h),Standard: c++20. - Braces on control flow:
forandifbodies use curly braces whenever the body spans more than one line (e.g. a nestedif, a wrapped statement, or multiple statements). A body that fits on a single line may omit braces.