Skip to content

Commit 0beb26e

Browse files
committed
Another attempt to fix GCC/MSCV const iterator
1 parent 3f41835 commit 0beb26e

1 file changed

Lines changed: 37 additions & 45 deletions

File tree

include/LockFreeSpscQueue.h

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)