@@ -210,38 +210,50 @@ class LockFreeSpscQueue
210210 struct ReadScope
211211 {
212212 // --- Custom Iterators (const and non-const) ---
213-
214- /* * @brief A read-only iterator for the ReadScope. */
215- class const_iterator
213+ template <bool IsConst>
214+ class any_iterator
216215 {
217216 public:
218- using iterator_category = std::forward_iterator_tag;
219- using value_type = const T;
220- using difference_type = std::ptrdiff_t ;
221- using pointer = const T*;
222- using reference = const T&;
223- using SpanConstIterator = typename std::span<const T>::iterator;
217+ using value_type = std::conditional_t <IsConst, const T, T>;
218+ using difference_type = std::ptrdiff_t ;
219+ using pointer = value_type*;
220+ using reference = value_type&;
221+ using SpanIterator = typename std::span<value_type>::iterator;
224222
225- const_iterator () = default ;
223+ any_iterator () = default ;
226224 reference operator *() const { return *m_current_iter; }
227225 pointer operator ->() const { return &(*m_current_iter); }
228226
229- const_iterator & operator ++() {
227+ any_iterator & operator ++() {
230228 ++m_current_iter;
231229 if (m_in_block1 && m_current_iter == m_block1_end) {
232230 m_current_iter = m_block2_begin;
233231 m_in_block1 = false ;
234232 }
235233 return *this ;
236234 }
237- const_iterator operator ++(int ) { const_iterator tmp = *this ; ++(*this ); return tmp; }
238- bool operator ==(const const_iterator& other) const = default ;
235+ any_iterator operator ++(int ) { any_iterator tmp = *this ; ++(*this ); return tmp; }
236+
237+ // Allow conversion from mutable iterator to const_iterator
238+ template <bool OtherIsConst>
239+ requires ( IsConst
240+ && !OtherIsConst
241+ && std::convertible_to<typename any_iterator<OtherIsConst>::SpanIterator,
242+ SpanIterator>)
243+ any_iterator (const any_iterator<OtherIsConst>& other)
244+ : m_current_iter(other.m_current_iter)
245+ , m_block1_end(other.m_block1_end)
246+ , m_block2_begin(other.m_block2_begin)
247+ , m_block2_end(other.m_block2_end)
248+ , m_in_block1(other.m_in_block1) {}
249+
250+ bool operator ==(const any_iterator& other) const = default ;
239251
240- protected: // Protected so the mutable iterator can access them
252+ private:
241253 friend struct ReadScope ;
242- const_iterator (SpanConstIterator b1_begin, SpanConstIterator b1_end,
243- SpanConstIterator b2_begin, SpanConstIterator b2_end,
244- bool is_begin)
254+ any_iterator (SpanIterator b1_begin, SpanIterator b1_end,
255+ SpanIterator b2_begin, SpanIterator b2_end,
256+ bool is_begin)
245257 : m_block1_end(b1_end), m_block2_begin(b2_begin), m_block2_end(b2_end)
246258 {
247259 if (is_begin) {
@@ -258,38 +270,18 @@ class LockFreeSpscQueue
258270 }
259271 }
260272
261- SpanConstIterator m_current_iter;
262- SpanConstIterator m_block1_end;
263- SpanConstIterator m_block2_begin;
264- SpanConstIterator m_block2_end;
273+ SpanIterator m_current_iter;
274+ SpanIterator m_block1_end;
275+ SpanIterator m_block2_begin;
276+ SpanIterator m_block2_end;
265277 bool m_in_block1 = false ;
278+
279+ template <bool > friend class any_iterator ; // Allow conversion access
266280 };
267281
268282 /* * @brief A mutable iterator for the ReadScope, enabling moves. */
269- class iterator : public const_iterator
270- {
271- public:
272- using value_type = T;
273- using pointer = T*;
274- using reference = T&;
275- using SpanIterator = typename std::span<T>::iterator;
276-
277- // Provide an explicit constructor that takes mutable iterators.
278- // This constructor correctly delegates to the const_iterator's base
279- // constructor, allowing the valid conversion from iterator-to-T
280- // to iterator-to-const-T to happen.
281- iterator (SpanIterator b1_begin, SpanIterator b1_end,
282- SpanIterator b2_begin, SpanIterator b2_end,
283- bool is_begin)
284- : const_iterator(b1_begin, b1_end, b2_begin, b2_end, is_begin) {}
285-
286- reference operator *() const {
287- return const_cast <reference>(const_iterator::operator *());
288- }
289- pointer operator ->() const {
290- return const_cast <pointer>(const_iterator::operator ->());
291- }
292- };
283+ using iterator = any_iterator<false >;
284+ using const_iterator = any_iterator<true >;
293285
294286 // --- Making ReadScope a C++20 Range (with const and non-const overloads) ---
295287 [[nodiscard]] iterator begin () {
0 commit comments