Version: v0.2.0
Status: Complete
Header: include/stratax/core/containers/Shape.hpp
Overview
Shape stores array dimension lengths and provides rank/element-count metadata for Stratax containers.
It is a lightweight metadata object built on Buffer<std::size_t> and is used by higher-level types such as Strides, Vector, Matrix, and Tensor.
Responsibilities
The Shape class is responsible for:
- Storing dimension lengths
- Reporting rank
- Reporting whether a shape is empty
- Computing total element count with overflow checking
- Providing validated dimension access
- Supporting comparison and iteration over dimensions
The Shape class is not responsible for:
- Owning numeric array element storage
- Performing numerical algorithms
- Multidimensional data access into tensors/matrices/vectors
- Mathematical operations on data values
Relationships
Shape
│
└── dims_ : Buffer<std::size_t>
Stored dimensions in axis order
Depends on:
Used by:
- Strides
- Vector
- Matrix
- Tensor
Related classes:
Internal Data
| Member | Description |
| Buffer<std::size_t> dims_ | Contiguous storage for all dimension lengths |
Invariants
The following conditions are always true:
- rank() equals dims_.size().
- empty() is equivalent to rank() == 0.
- Dimensions are stored in axis order from outermost to innermost.
- operator== compares both rank and all dimension values.
- elements() checks multiplication overflow and throws on overflow.
Public Interface
Constructors
Default Constructor
Constructs an empty rank-0 shape.
Complexity
Throws
Variadic Integral Constructor
requires (sizeof...(Dims) > 0)
Shape(Dims... dims);
Matches signed and unsigned integral types, excluding character-like types.
Constructs a shape from one or more integral dimensions.
Complexity
Throws
Initializer List + Tag Constructor
Shape(std::initializer_list<std::size_t> list, allow_zero_t allow_zero);
Constructs a shape from explicit dimensions and documents zero-dimension intent.
Complexity
Buffer Copy Constructor
Shape(const Buffer<std::size_t>& dims);
Constructs a shape by copying dimensions from a buffer.
Complexity
Buffer Copy + Tag Constructor
Shape(const Buffer<std::size_t>& dims, allow_zero_t allow_zero);
Constructs a shape by copying dimensions from a buffer and documenting zero-dimension intent.
Complexity
Buffer Move Constructor
Shape(Buffer<std::size_t>&& dims);
Constructs a shape by taking ownership of dimension storage.
Complexity
std::vector Constructor
Shape(const std::vector<std::size_t>& dims);
Constructs a shape by copying dimensions from a standard vector.
Complexity
Throws
Destructor
Default destructor.
Complexity
Methods
elements()
[[nodiscard]] std::size_t elements() const;
Returns the product of all dimensions. Empty shape returns 0.
Complexity
Throws
rank()
[[nodiscard]] std::size_t rank() const;
Returns the number of stored dimensions.
Complexity
empty()
[[nodiscard]] bool empty() const noexcept;
Returns true if rank is zero.
Complexity
swap()
void swap(Shape& other) noexcept;
Exchanges dimension storage with another shape.
Complexity
begin()/end()
auto begin() noexcept;
auto end() noexcept;
auto begin() const noexcept;
auto end() const noexcept;
Provides mutable/const iteration over stored dimensions.
Complexity
Assignment Operators
Shape uses compiler-generated copy and move assignment operators.
Copy Assignment
Shape& operator=(const Shape&) = default;
Complexity
Move Assignment
Shape& operator=(Shape&&) noexcept = default;
Complexity
Operators
operator()
const std::size_t& operator()(std::size_t index) const;
Returns dimension at index with bounds validation.
Complexity
Throws
operator[]
const std::size_t& operator[](std::ptrdiff_t index) const;
Returns dimension at signed index. Negative indices count from the end.
Complexity
Throws
operator== / operator!=
[[nodiscard]]
bool operator==(
const Shape& other)
const noexcept;
[[nodiscard]]
bool operator!=(
const Shape& other)
const noexcept;
bool operator!=(const A &lhs, const A &rhs)
Compares two array-like containers for inequality.
bool operator==(const A &lhs, const A &rhs)
Compares two array-like containers for exact equality.
Compares two shapes by rank and all dimensions.
Complexity
stream operator
std::ostream& operator<<(std::ostream& os, const Shape& shape);
Writes shape in tuple-like form, for example (2, 3, 4) and (5,) for rank-1.
Complexity
Complexity Summary
| Operation | Complexity |
| Default construction | O(1) |
| Variadic construction | O(n) |
| Initializer-list + tag construction | O(n) |
| Buffer copy construction | O(n) |
| Buffer move construction | O(1) |
| std::vector construction | O(n) |
| Copy assignment | O(n) |
| Move assignment | O(1) |
| Destruction | O(n) |
| elements() | O(n) |
| rank() | O(1) |
| empty() | O(1) |
| operator() | O(1) |
| operator[] | O(1) |
| operator== / operator!= | O(n) |
| Iteration | O(n) |
| swap() | O(1) |
Examples
Creating Shapes
Shape a;
Shape b(2, 3, 4);
Shape c{std::vector<std::size_t>{1, 5, 7}};
Accessing Dimensions
Shape s(3, 224, 224);
auto first = s(0);
auto last = s[-1];
Printing
Shape s(3, 224, 224);
std::cout << s << '\n';
Design Notes
Shape stores only metadata and intentionally avoids owning numeric element data.
Dimension storage is contiguous through Buffer<std::size_t>, which keeps shape operations lightweight and iteration/cache friendly. Data containers (Vector, Matrix, Tensor) use Shape to define layout semantics.
Future Improvements
- Add cbegin()/cend() convenience methods
- Add shape utility helpers (concat, slice, transpose-spec helpers)
- Add optional constexpr-friendly construction for fixed-rank usage
See Also