A modern, high-performance n-dimensional array implementation using C++20/23 features.
- C++20 Concepts: Type-safe template constraints with clear error messages
- Requires Clauses: Compile-time validation of template parameters
- Spaceship Operator (
<=>): Full comparison support with auto-generated operators - consteval: Compile-time only functions for zero runtime overhead
- C++23 Multidimensional Subscript:
array[x, y, z]syntax (when available)
- Static constexpr steps: Stride calculations computed once at compile-time, zero per-instance overhead
- Compiler-friendly inlining: Small hot path functions optimized for automatic inlining
[[nodiscard]]: Prevents accidental value discards- Zero-overhead abstraction: Fully constexpr, no runtime cost for multidimensional indexing
- Iterator support: Compatible with STL algorithms and range-based for loops
- Type aliases: Standard container-like interface
- Checked and unchecked access:
at()for safety,unsafe_at()for performance - Dimension introspection: Query dimension count and sizes at compile-time
- Aggregate initialization: Direct brace initialization with compile-time size validation
#include "nd_array.h"
constexpr int xMax = 2;
constexpr int yMax = 2;
constexpr int zMax = 2;
constexpr auto ndarray = nd_array<int, xMax, yMax, zMax>{
1, 2,
3, 4,
5, 6,
7, 8,
};
// Compile-time validation
static_assert(ndarray.at(0,0,0) == 1);
static_assert(ndarray.at(1,0,0) == 2);
static_assert(ndarray.at(0,1,0) == 3);
static_assert(ndarray.at(1,1,0) == 4);
static_assert(ndarray.at(0,0,1) == 5);
static_assert(ndarray.at(1,0,1) == 6);
static_assert(ndarray.at(0,1,1) == 7);
static_assert(ndarray.at(1,1,1) == 8);// Iterator support - works with STL algorithms
auto arr = nd_array<int, 3, 3>{1,2,3,4,5,6,7,8,9};
// Range-based for loop
for (const auto& elem : arr) {
std::cout << elem << " ";
}
// STL algorithms
auto sum = std::accumulate(arr.begin(), arr.end(), 0);
auto max = *std::max_element(arr.begin(), arr.end());
// Dimension introspection
static_assert(arr.dimension_count() == 2);
static_assert(arr.dimension_size(0) == 3);
static_assert(arr.dimension_size(1) == 3);
// Comparisons (C++20 spaceship operator)
auto arr1 = nd_array<int, 2, 2>{1, 2, 3, 4};
auto arr2 = nd_array<int, 2, 2>{1, 2, 3, 4};
static_assert(arr1 == arr2);
static_assert(arr1 <= arr2);
// Performance-critical unchecked access
constexpr auto value = arr.unsafe_at(1, 1); // No bounds checking// Concepts ensure only arithmetic types are allowed
nd_array<int, 2, 2> int_array{}; // OK
nd_array<double, 2, 2> float_array{}; // OK
nd_array<std::string, 2, 2> str_array{}; // Compile error: requires Arithmetic
// Compile-time dimension validation
constexpr auto arr = nd_array<int, 2, 3>{1,2,3,4,5,6};
arr.at(0, 0); // OK
arr.at(0, 0, 0); // Compile error: wrong number of indices- Inherits from
std::array<T, (N * ...)>for optimal memory layout - No virtual functions, no vtable overhead
- Contiguous memory storage in row-major order
- All dimension calculations happen at compile-time using
consteval - Index stride calculations are static constexpr (computed once per type)
- Full constexpr support for compile-time array operations
- C++20 or later
- Compiler support for:
- Concepts and requires clauses
- consteval
- Spaceship operator
- (Optional) C++23 multidimensional subscript for
operator[]syntax
# C++20 build
g++ -std=c++20 -Wall -Wextra -O3 -o main main.cpp
# With C++23 features
g++ -std=c++23 -Wall -Wextra -O3 -o main main.cpp- ✅ Replaced
uint32_twithstd::size_tfor better portability - ✅ Added C++20 concepts (
Arithmetic,Integral) for type safety - ✅ Added requires clauses for compile-time validation
- ✅ Implemented C++20 spaceship operator for comparisons
- ✅ Used
constevalfor compile-time only functions - ✅ Added C++23 multidimensional subscript operator
- ✅ Added
[[nodiscard]]attributes - ✅ Exposed iterator interface for range-based operations
- ✅ Added standard container type aliases
- ✅ Made
stepsarray static constexpr (no per-instance storage) - ✅ Removed redundant
seqmember variable - ✅ Optimized hot path functions for automatic compiler inlining
- ✅ Improved
make_steps()withconstevalandif constexpr - ✅ Made all helper functions static to avoid
thispointer overhead - ✅ Used
std::index_sequence_forto generate sequences on-demand - ✅ Optimized index calculation with fold expressions
- Memory: Reduced per-instance size by ~32 bytes (removed
seqand madestepsstatic) - Compile-time: More work at compile-time, zero runtime overhead
- Runtime: Identical or better performance due to better inlining and optimizations
- Type safety: Better error messages and compile-time guarantees
Public domain / MIT - use as you wish!