@@ -35,20 +35,22 @@ class flat_matrix {
3535 using value_type = T;
3636 // / @brief Unsigned integral type used for sizes and indices
3737 using size_type = std::size_t ;
38+ // / @brief The underlying contiguous storage container
39+ using container_type = std::vector<value_type>;
3840 // / @brief Reference to an element
39- using reference = value_type& ;
41+ using reference = typename container_type::reference ;
4042 // / @brief Const reference to an element
41- using const_reference = const value_type& ;
42- // / @brief Span type representing a non-owning uniform row of elements
43- using row_type = std::span<value_type >;
44- // / @brief Const span type representing a non-owning uniform const row of elements
45- using const_row_type = std::span< const value_type >;
43+ using const_reference = typename container_type::const_reference ;
44+ // / @brief Subrange type representing a non-owning uniform row of elements
45+ using row_type = std::ranges::subrange< typename container_type::iterator >;
46+ // / @brief Const subrange type representing a non-owning uniform const row of elements
47+ using const_row_type = std::ranges::subrange< typename container_type::const_iterator >;
4648
4749 // --- iterators ---
4850
4951 // / @brief Random access iterator over the rows of the `flat_matrix`.
5052 // /
51- // / This iterator dereferences to a `row_type` (span of elements representing a single matrix row),
53+ // / This iterator dereferences to a `row_type` (subrange of elements representing a single matrix row),
5254 // / allowing efficient iteration and random access. It calculates the memory offsets mathematically
5355 // / based on the column dimension.
5456 // /
@@ -57,44 +59,48 @@ class flat_matrix {
5759 // / @warning Invalidated when the `flat_matrix` structural dimensions are modified or memory is reallocated.
5860 template <bool Const>
5961 class row_iterator {
60- using data_ptr_type = std::conditional_t <Const, const T*, T*>;
62+ using data_iter_type = std::conditional_t <
63+ Const,
64+ typename container_type::const_iterator,
65+ typename container_type::iterator>;
6166
6267 public:
6368 // / @brief Satisfies random access iterator concept
6469 using iterator_concept = std::random_access_iterator_tag;
6570 // / @brief Legacy iterator category (random access)
6671 using iterator_category = std::random_access_iterator_tag;
67- // / @brief Type of row this iterator dereferences to (span or const span )
72+ // / @brief Type of row this iterator dereferences to (subrange or const subrange )
6873 using value_type = std::conditional_t <Const, const_row_type, row_type>;
6974 // / @brief Signed integral difference type
7075 using difference_type = std::ptrdiff_t ;
7176 // / @brief Pointer type (void because iterators dereference to spans)
7277 using pointer = void ;
73- // / @brief Reference type (span of elements)
78+ // / @brief Reference type (subrange of elements)
7479 using reference = value_type;
7580
7681 // / @brief Default constructor creates a null iterator
7782 row_iterator () = default ;
7883
7984 // / @brief Constructs an iterator pointing to a specific row.
80- // / @param data_ptr Pointer to the underlying flat element data
85+ // / @param data_iter Iterator to the underlying flat element data
8186 // / @param n_cols The number of columns in the matrix
8287 // / @param row_idx The index of the row this iterator currently points to
83- row_iterator (data_ptr_type data_ptr , size_type n_cols, size_type row_idx) noexcept
84- : _data_ptr(data_ptr ), _row_size(n_cols), _row_idx(row_idx) {}
88+ row_iterator (data_iter_type data_iter , size_type n_cols, size_type row_idx) noexcept
89+ : _data_iter(data_iter ), _row_size(n_cols), _row_idx(row_idx) {}
8590
8691 // / @brief Implicit conversion from mutable to const iterator
8792 // / @return A const iterator pointing to the same row
8893 operator row_iterator<true >() const noexcept
8994 requires (not Const)
9095 {
91- return row_iterator<true >(this ->_data_ptr , this ->_row_size , this ->_row_idx );
96+ return row_iterator<true >(this ->_data_iter , this ->_row_size , this ->_row_idx );
9297 }
9398
9499 // / @brief Dereferences the iterator to the current row.
95- // / @return A span representing the row at the current position
100+ // / @return A subrange representing the row at the current position
96101 [[nodiscard]] reference operator *() const noexcept {
97- return reference (this ->_data_ptr + this ->_row_idx * this ->_row_size , this ->_row_size );
102+ const auto row_beg = this ->_data_iter + this ->_row_idx * this ->_row_size ;
103+ return reference (row_beg, row_beg + this ->_row_size );
98104 }
99105
100106 // / @brief Random access to a row at an offset from the current position.
@@ -206,7 +212,7 @@ class flat_matrix {
206212 }
207213
208214 private:
209- data_ptr_type _data_ptr{ nullptr } ;
215+ data_iter_type _data_iter ;
210216 size_type _row_size{0uz};
211217 size_type _row_idx{0uz};
212218 };
@@ -439,7 +445,7 @@ class flat_matrix {
439445 return ;
440446 }
441447
442- std::vector<value_type> new_data (new_rows * new_cols, value);
448+ container_type new_data (new_rows * new_cols, value);
443449 const auto min_rows = std::min (this ->_n_rows , new_rows);
444450 const auto min_cols = std::min (this ->_n_cols , new_cols);
445451
@@ -474,20 +480,22 @@ class flat_matrix {
474480
475481 // / @brief Returns the row at the given index without bounds checking.
476482 // / @param r The index of the row to access
477- // / @return A span representing the row at index r
483+ // / @return A subrange representing the row at index r
478484 // / @pre `r < n_rows()`; otherwise Undefined Behavior
479485 // / @warning No bounds checking is performed for performance.
480486 [[nodiscard]] row_type operator [](size_type r) {
481- return row_type (this ->_data .data () + r * this ->_n_cols , this ->_n_cols );
487+ const auto row_beg = this ->_data .begin () + r * this ->_n_cols ;
488+ return row_type (row_beg, row_beg + this ->_n_cols );
482489 }
483490
484491 // / @brief Returns a const row at the given index without bounds checking.
485492 // / @param r The index of the row to access
486- // / @return A const span representing the row at index r
493+ // / @return A const subrange representing the row at index r
487494 // / @pre `r < n_rows()`; otherwise Undefined Behavior
488495 // / @warning No bounds checking is performed.
489496 [[nodiscard]] const_row_type operator [](size_type r) const {
490- return const_row_type (this ->_data .data () + r * this ->_n_cols , this ->_n_cols );
497+ const auto row_beg = this ->_data .begin () + r * this ->_n_cols ;
498+ return const_row_type (row_beg, row_beg + this ->_n_cols );
491499 }
492500
493501 // / @brief Returns a reference to an element without bounds checking.
@@ -512,7 +520,7 @@ class flat_matrix {
512520
513521 // / @brief Returns the row at the given index with bounds checking.
514522 // / @param r The index of the row
515- // / @return A span representing the row at index r
523+ // / @return A subrange representing the row at index r
516524 // / @exception std::out_of_range If `r >= n_rows()`
517525 [[nodiscard]] row_type at (size_type r) {
518526 this ->_check_row (r);
@@ -521,7 +529,7 @@ class flat_matrix {
521529
522530 // / @brief Returns a const row at the given index with bounds checking.
523531 // / @param r The index of the row
524- // / @return A const span representing the row at index r
532+ // / @return A const subrange representing the row at index r
525533 // / @exception std::out_of_range If `r >= n_rows()`
526534 [[nodiscard]] const_row_type at (size_type r) const {
527535 this ->_check_row (r);
@@ -551,60 +559,60 @@ class flat_matrix {
551559 }
552560
553561 // / @brief Returns the first row without bounds checking.
554- // / @return A span representing the first row
562+ // / @return A subrange representing the first row
555563 // / @pre Matrix must not be empty; otherwise Undefined Behavior
556564 // / @warning No bounds checking is performed.
557565 [[nodiscard]] row_type front () noexcept {
558566 return (*this )[0uz];
559567 }
560568
561569 // / @brief Returns a const reference to the first row without bounds checking.
562- // / @return A const span representing the first row
570+ // / @return A const subrange representing the first row
563571 // / @pre Matrix must not be empty; otherwise Undefined Behavior
564572 // / @warning No bounds checking is performed.
565573 [[nodiscard]] const_row_type front () const noexcept {
566574 return (*this )[0uz];
567575 }
568576
569577 // / @brief Returns the last row without bounds checking.
570- // / @return A span representing the last row
578+ // / @return A subrange representing the last row
571579 // / @pre Matrix must not be empty; otherwise Undefined Behavior
572580 // / @warning No bounds checking is performed.
573581 [[nodiscard]] row_type back () noexcept {
574582 return (*this )[this ->_n_rows - 1uz];
575583 }
576584
577585 // / @brief Returns a const reference to the last row without bounds checking.
578- // / @return A const span representing the last row
586+ // / @return A const subrange representing the last row
579587 // / @pre Matrix must not be empty; otherwise Undefined Behavior
580588 // / @warning No bounds checking is performed.
581589 [[nodiscard]] const_row_type back () const noexcept {
582590 return (*this )[this ->_n_rows - 1uz];
583591 }
584592
585593 // / @brief Explicitly named alias for `front()` yielding the first row.
586- // / @return A span representing the first row
594+ // / @return A subrange representing the first row
587595 // / @pre Matrix must not be empty; otherwise Undefined Behavior
588596 [[nodiscard]] row_type front_row () noexcept {
589597 return this ->front ();
590598 }
591599
592600 // / @brief Explicitly named alias for `front()` yielding the first const row.
593- // / @return A const span representing the first row
601+ // / @return A const subrange representing the first row
594602 // / @pre Matrix must not be empty; otherwise Undefined Behavior
595603 [[nodiscard]] const_row_type front_row () const noexcept {
596604 return this ->front ();
597605 }
598606
599607 // / @brief Explicitly named alias for `back()` yielding the last row.
600- // / @return A span representing the last row
608+ // / @return A subrange representing the last row
601609 // / @pre Matrix must not be empty; otherwise Undefined Behavior
602610 [[nodiscard]] row_type back_row () noexcept {
603611 return this ->back ();
604612 }
605613
606614 // / @brief Explicitly named alias for `back()` yielding the last const row.
607- // / @return A const span representing the last row
615+ // / @return A const subrange representing the last row
608616 // / @pre Matrix must not be empty; otherwise Undefined Behavior
609617 [[nodiscard]] const_row_type back_row () const noexcept {
610618 return this ->back ();
@@ -644,15 +652,15 @@ class flat_matrix {
644652
645653 // / @brief Semantically symmetric alias for `at(r)` returning a bounds-checked row.
646654 // / @param r The row index
647- // / @return A span representing the row
655+ // / @return A subrange representing the row
648656 // / @exception std::out_of_range If `r >= n_rows()`
649657 [[nodiscard]] row_type row (size_type r) {
650658 return this ->at (r);
651659 }
652660
653661 // / @brief Semantically symmetric alias for `at(r)` returning a bounds-checked const row.
654662 // / @param r The row index
655- // / @return A const span representing the row
663+ // / @return A const subrange representing the row
656664 // / @exception std::out_of_range If `r >= n_rows()`
657665 [[nodiscard]] const_row_type row (size_type r) const {
658666 return this ->at (r);
@@ -712,41 +720,46 @@ class flat_matrix {
712720 return this ->_data .size ();
713721 }
714722
715- // / @brief Returns a span over all element data in flattened 1D form.
716- // / @return A span of all elements in the underlying `_data` array.
723+ // / @brief Returns a subrange of all element data in flattened 1D form.
724+ // / @return A subrange of all elements in the underlying `_data` array.
717725 [[nodiscard]] row_type data_view () noexcept {
718726 return row_type (this ->_data );
719727 }
720728
721- // / @brief Returns a const span over all element data in flattened 1D form.
722- // / @return A const span of all elements in the underlying `_data` array.
729+ // / @brief Returns a const subrange of all element data in flattened 1D form.
730+ // / @return A const subrange of all elements in the underlying `_data` array.
723731 [[nodiscard]] const_row_type data_view () const noexcept {
724732 return const_row_type (this ->_data );
725733 }
726734
727735 // / @brief Returns a reference to the underlying flat data container.
728736 // / @return A mutable reference to the underlying `_data` array.
729737 // / @warning Modifying this vector directly can fatally corrupt the matrix structure. Use for advanced operations only.
730- [[nodiscard]] std::vector<value_type> & data_storage () noexcept {
738+ [[nodiscard]] container_type & data_storage () noexcept {
731739 return this ->_data ;
732740 }
733741
734742 // / @brief Returns a const reference to the underlying flat data container.
735743 // / @return A const reference to the underlying `_data` array.
736- [[nodiscard]] const std::vector<value_type> & data_storage () const noexcept {
744+ [[nodiscard]] const container_type & data_storage () const noexcept {
737745 return this ->_data ;
738746 }
739747
740748 // / @brief Returns a raw pointer to the underlying flat data array.
741749 // / @return A raw pointer to the first element in the `_data` array.
742- // / @warning No bounds checking is performed.
743- [[nodiscard]] value_type* data_ptr () noexcept {
750+ // / @warning Not available for boolean matrices.
751+ [[nodiscard]] value_type* data_ptr () noexcept
752+ requires(not std::same_as<value_type, bool >)
753+ {
744754 return this ->_data .data ();
745755 }
746756
747757 // / @brief Returns a const raw pointer to the underlying flat data array.
748758 // / @return A const raw pointer to the first element in the `_data` array.
749- [[nodiscard]] const value_type* data_ptr () const noexcept {
759+ // / @warning Not available for boolean matrices.
760+ [[nodiscard]] const value_type* data_ptr () const noexcept
761+ requires(not std::same_as<value_type, bool >)
762+ {
750763 return this ->_data .data ();
751764 }
752765
@@ -1009,7 +1022,7 @@ class flat_matrix {
10091022 this ->_n_rows = col_size;
10101023
10111024 // pre-allocate new vector to guarantee O(RxC) structural shift, avoiding cubic complexity with multiple inserts
1012- std::vector<value_type> new_data;
1025+ container_type new_data;
10131026 new_data.reserve (this ->_n_rows * (this ->_n_cols + 1uz));
10141027
10151028 auto r_it = std::ranges::begin (r);
@@ -1038,7 +1051,7 @@ class flat_matrix {
10381051 else {
10391052 // create a temporary sized range and recursively call the method to leverage the sized range logic,
10401053 // ensuring strong exception guarantee for unsized input
1041- this ->insert_col (pos, std::ranges::to<std::vector<value_type> >(std::forward<R>(r)));
1054+ this ->insert_col (pos, std::ranges::to<container_type >(std::forward<R>(r)));
10421055 }
10431056 }
10441057
@@ -1074,7 +1087,7 @@ class flat_matrix {
10741087 ));
10751088 }
10761089
1077- std::vector<value_type> new_data;
1090+ container_type new_data;
10781091 new_data.reserve (this ->_n_rows * (this ->_n_cols + 1uz));
10791092
10801093 for (size_type r_idx = 0uz; r_idx < this ->_n_rows ; ++r_idx) {
@@ -1123,7 +1136,7 @@ class flat_matrix {
11231136 return ;
11241137 }
11251138
1126- std::vector<value_type> new_data;
1139+ container_type new_data;
11271140 new_data.reserve (this ->_n_rows * (this ->_n_cols - 1uz));
11281141
11291142 for (size_type r_idx = 0uz; r_idx < this ->_n_rows ; ++r_idx) {
@@ -1151,28 +1164,28 @@ class flat_matrix {
11511164 // / @return Iterator to the first row
11521165 // / @note Iterator invalidated by structural modifications
11531166 [[nodiscard]] iterator begin () noexcept {
1154- return iterator (this ->_data .data (), this ->_n_cols , 0uz);
1167+ return iterator (this ->_data .begin (), this ->_n_cols , 0uz);
11551168 }
11561169
11571170 // / @brief Returns a mutable iterator past the last row (end sentinel).
11581171 // / @return Iterator one position past the last row
11591172 // / @note Iterator invalidated by structural modifications
11601173 [[nodiscard]] iterator end () noexcept {
1161- return iterator (this ->_data .data (), this ->_n_cols , this ->_n_rows );
1174+ return iterator (this ->_data .begin (), this ->_n_cols , this ->_n_rows );
11621175 }
11631176
11641177 // / @brief Returns a const iterator to the first row.
11651178 // / @return Const iterator to the first row
11661179 // / @note Iterator invalidated by structural modifications
11671180 [[nodiscard]] const_iterator begin () const noexcept {
1168- return const_iterator (this ->_data .data (), this ->_n_cols , 0uz);
1181+ return const_iterator (this ->_data .begin (), this ->_n_cols , 0uz);
11691182 }
11701183
11711184 // / @brief Returns a const iterator past the last row (end sentinel).
11721185 // / @return Const iterator one position past the last row
11731186 // / @note Iterator invalidated by structural modifications
11741187 [[nodiscard]] const_iterator end () const noexcept {
1175- return const_iterator (this ->_data .data (), this ->_n_cols , this ->_n_rows );
1188+ return const_iterator (this ->_data .begin (), this ->_n_cols , this ->_n_rows );
11761189 }
11771190
11781191 // / @brief Returns a const iterator to the first row (explicit const form).
@@ -1289,7 +1302,7 @@ class flat_matrix {
12891302
12901303 size_type _n_rows{0uz};
12911304 size_type _n_cols{0uz};
1292- std::vector<value_type> _data;
1305+ container_type _data;
12931306};
12941307
12951308} // namespace gl
0 commit comments