refs #698 CSequence iterator should be random access to improve STL algorithm efficiency.

This commit is contained in:
Mathew Sutcliffe
2016-07-04 17:41:00 +01:00
parent a209f961a6
commit 323a5bb12f
2 changed files with 76 additions and 54 deletions

View File

@@ -439,12 +439,12 @@ namespace BlackMisc
}; };
/*! /*!
* \brief Generic type-erased const bidirectional iterator with value semantics. * \brief Generic type-erased const random access iterator with value semantics.
* \tparam T the value_type of the container being iterated over. * \tparam T the value_type of the container being iterated over.
* *
* Can take any suitable iterator type as its implementation at runtime. * Can take any suitable iterator type as its implementation at runtime.
*/ */
template <class T> class ConstBidirectionalIterator template <class T> class ConstRandomAccessIterator
{ {
public: public:
//! \brief STL compatibility //! \brief STL compatibility
@@ -455,38 +455,38 @@ namespace BlackMisc
typedef const T &reference; typedef const T &reference;
typedef const T *const_pointer; typedef const T *const_pointer;
typedef const T &const_reference; typedef const T &const_reference;
typedef std::bidirectional_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
//! @} //! @}
//! \brief Default constructor. //! \brief Default constructor.
ConstBidirectionalIterator() {} ConstRandomAccessIterator() {}
/*! /*!
* \brief Copy constructor. * \brief Copy constructor.
*/ */
ConstBidirectionalIterator(const ConstBidirectionalIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {} ConstRandomAccessIterator(const ConstRandomAccessIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
/*! /*!
* \brief Move constructor. * \brief Move constructor.
*/ */
ConstBidirectionalIterator(ConstBidirectionalIterator &&other) noexcept : m_pimpl(other.m_pimpl.take()) {} ConstRandomAccessIterator(ConstRandomAccessIterator &&other) noexcept : m_pimpl(other.m_pimpl.take()) {}
/*! /*!
* \brief Copy assignment. * \brief Copy assignment.
*/ */
ConstBidirectionalIterator &operator =(const ConstBidirectionalIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; } ConstRandomAccessIterator &operator =(const ConstRandomAccessIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
/*! /*!
* \brief Move assignment. * \brief Move assignment.
*/ */
ConstBidirectionalIterator &operator =(ConstBidirectionalIterator &&other) noexcept { m_pimpl.reset(other.m_pimpl.take()); return *this; } ConstRandomAccessIterator &operator =(ConstRandomAccessIterator &&other) noexcept { m_pimpl.reset(other.m_pimpl.take()); return *this; }
/*! /*!
* \brief Create a new iterator with a specific implementation type. * \brief Create a new iterator with a specific implementation type.
* \tparam I Becomes the iterator's implementation type. * \tparam I Becomes the iterator's implementation type.
* \param i Initial value for the iterator. The value is copied. * \param i Initial value for the iterator. The value is copied.
*/ */
template <class I> static ConstBidirectionalIterator fromImpl(I i) { return ConstBidirectionalIterator(new Pimpl<I>(std::move(i))); } template <class I> static ConstRandomAccessIterator fromImpl(I i) { return ConstRandomAccessIterator(new Pimpl<I>(std::move(i))); }
/*! /*!
* \brief Returns a reference to the object pointed to. * \brief Returns a reference to the object pointed to.
@@ -505,86 +505,95 @@ namespace BlackMisc
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator &operator ++() { Q_ASSERT(m_pimpl); ++*pimpl(); return *this; } ConstRandomAccessIterator &operator ++() { Q_ASSERT(m_pimpl); ++*pimpl(); return *this; }
/*! /*!
* \brief Postfix increment operator advances the iterator. * \brief Postfix increment operator advances the iterator.
* \return Copy of the iterator in the old position. * \return Copy of the iterator in the old position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator ++(int) { Q_ASSERT(m_pimpl); auto copy = *this; ++*pimpl(); return copy; } ConstRandomAccessIterator operator ++(int) { Q_ASSERT(m_pimpl); auto copy = *this; ++*pimpl(); return copy; }
/*! /*!
* \brief Prefix decrement operator backtracks the iterator. * \brief Prefix decrement operator backtracks the iterator.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator &operator --() { Q_ASSERT(m_pimpl); --*pimpl(); return *this; } ConstRandomAccessIterator &operator --() { Q_ASSERT(m_pimpl); --*pimpl(); return *this; }
/*! /*!
* \brief Postfix decrement operator backtracks the iterator. * \brief Postfix decrement operator backtracks the iterator.
* \return Copy of the iterator at the old position. * \return Copy of the iterator at the old position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator --(int) { Q_ASSERT(m_pimpl); auto copy = *this; --*pimpl(); return copy; } ConstRandomAccessIterator operator --(int) { Q_ASSERT(m_pimpl); auto copy = *this; --*pimpl(); return copy; }
/*! /*!
* \brief Advance the iterator by a certain amount. * \brief Advance the iterator by a certain amount.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator +=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() += n; return *this; } ConstRandomAccessIterator operator +=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() += n; return *this; }
/*! /*!
* \brief Advance the iterator by a certain amount. * \brief Advance the iterator by a certain amount.
* \return Copy of the iterator in its new position. * \return Copy of the iterator in its new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator +(difference_type n) const { auto copy = *this; return copy += n; } //! @{
friend ConstRandomAccessIterator operator +(const ConstRandomAccessIterator &i, difference_type n) { auto copy = i; return copy += n; }
friend ConstRandomAccessIterator operator +(difference_type n, const ConstRandomAccessIterator &i) { auto copy = i; return copy += n; }
//! @}
/*! /*!
* \brief Backtrack the iterator by a certain amount. * \brief Backtrack the iterator by a certain amount.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator -=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() -= n; return *this; } ConstRandomAccessIterator operator -=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() -= n; return *this; }
/*! /*!
* \brief Backtrack the iterator by a certain amount. * \brief Backtrack the iterator by a certain amount.
* \return Copy of the iterator in its new position. * \return Copy of the iterator in its new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
ConstBidirectionalIterator operator -(difference_type n) const { auto copy = *this; return copy -= n; } ConstRandomAccessIterator operator -(difference_type n) const { auto copy = *this; return copy -= n; }
/*! /*!
* \brief Return the distance between two iterators. * \brief Return the distance between two iterators.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
difference_type operator -(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); } difference_type operator -(const ConstRandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); }
/*! /*!
* \brief Test for equality. * \brief Test for equality.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
bool operator ==(const ConstBidirectionalIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); } bool operator ==(const ConstRandomAccessIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); }
/*! /*!
* \brief Test for inequality. * \brief Test for inequality.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
bool operator !=(const ConstBidirectionalIterator &other) const { return !(*this == other); } bool operator !=(const ConstRandomAccessIterator &other) const { return !(*this == other); }
/*! /*!
* \brief For sorting. * \brief For sorting.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
//! @{ //! @{
bool operator <(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); } bool operator <(const ConstRandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); }
bool operator >(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() > *other.pimpl(); } bool operator >(const ConstRandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() > *other.pimpl(); }
bool operator <=(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() <= *other.pimpl(); } bool operator <=(const ConstRandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() <= *other.pimpl(); }
bool operator >=(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() >= *other.pimpl(); } bool operator >=(const ConstRandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() >= *other.pimpl(); }
//! @} //! @}
/*!
* \brief Subscript operator.
* \pre `(*this + n)` must be dereferenceable.
*/
reference operator [](difference_type n) const { return *(*this + n); }
/*! /*!
* \brief Return opaque pointer to underlying implementation iterator object. * \brief Return opaque pointer to underlying implementation iterator object.
* \pre The iterator must have been initialized. * \pre The iterator must have been initialized.
@@ -616,7 +625,9 @@ namespace BlackMisc
{ {
public: public:
static_assert(std::is_same<T, typename std::iterator_traits<I>::value_type>::value, static_assert(std::is_same<T, typename std::iterator_traits<I>::value_type>::value,
"ConstBidirectionalIterator must be initialized from an iterator with the same value_type."); "ConstRandomAccessIterator must be initialized from an iterator with the same value_type.");
static_assert(std::is_same<typename std::iterator_traits<I>::iterator_category, std::random_access_iterator_tag>::value,
"ConstRandomAccessIterator must be initialized from a random access iterator.");
Pimpl(I &&i) : m_impl(std::move(i)) {} Pimpl(I &&i) : m_impl(std::move(i)) {}
virtual PimplBase *clone() const override { return new Pimpl(*this); } virtual PimplBase *clone() const override { return new Pimpl(*this); }
virtual const_reference operator *() const override { return *m_impl; } virtual const_reference operator *() const override { return *m_impl; }
@@ -639,7 +650,7 @@ namespace BlackMisc
using PimplPtr = QScopedPointer<PimplBase>; using PimplPtr = QScopedPointer<PimplBase>;
PimplPtr m_pimpl; PimplPtr m_pimpl;
explicit ConstBidirectionalIterator(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl() explicit ConstRandomAccessIterator(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl()
// using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const // using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const
PimplBase *pimpl() { return m_pimpl.data(); } PimplBase *pimpl() { return m_pimpl.data(); }
@@ -652,7 +663,7 @@ namespace BlackMisc
* *
* Can take any suitable iterator type as its implementation at runtime. * Can take any suitable iterator type as its implementation at runtime.
*/ */
template <class T> class BidirectionalIterator template <class T> class RandomAccessIterator
{ {
public: public:
//! \brief STL compatibility //! \brief STL compatibility
@@ -663,38 +674,38 @@ namespace BlackMisc
typedef T &reference; typedef T &reference;
typedef const T *const_pointer; typedef const T *const_pointer;
typedef const T &const_reference; typedef const T &const_reference;
typedef std::bidirectional_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
//! @} //! @}
//! \brief Default constructor. //! \brief Default constructor.
BidirectionalIterator() {} RandomAccessIterator() {}
/*! /*!
* \brief Copy constructor. * \brief Copy constructor.
*/ */
BidirectionalIterator(const BidirectionalIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {} RandomAccessIterator(const RandomAccessIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
/*! /*!
* \brief Move constructor. * \brief Move constructor.
*/ */
BidirectionalIterator(BidirectionalIterator &&other) noexcept : m_pimpl(other.m_pimpl.take()) {} RandomAccessIterator(RandomAccessIterator &&other) noexcept : m_pimpl(other.m_pimpl.take()) {}
/*! /*!
* \brief Copy assignment. * \brief Copy assignment.
*/ */
BidirectionalIterator &operator =(const BidirectionalIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; } RandomAccessIterator &operator =(const RandomAccessIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
/*! /*!
* \brief Move assignment. * \brief Move assignment.
*/ */
BidirectionalIterator &operator =(BidirectionalIterator &&other) noexcept { m_pimpl.reset(other.m_pimpl.take()); return *this; } RandomAccessIterator &operator =(RandomAccessIterator &&other) noexcept { m_pimpl.reset(other.m_pimpl.take()); return *this; }
/*! /*!
* \brief Create a new iterator with a specific implementation type. * \brief Create a new iterator with a specific implementation type.
* \tparam I Becomes the iterator's implementation type. * \tparam I Becomes the iterator's implementation type.
* \param i Initial value for the iterator. The value is copied. * \param i Initial value for the iterator. The value is copied.
*/ */
template <class I> static BidirectionalIterator fromImpl(I i) { return BidirectionalIterator(new Pimpl<I>(std::move(i))); } template <class I> static RandomAccessIterator fromImpl(I i) { return RandomAccessIterator(new Pimpl<I>(std::move(i))); }
/*! /*!
* \brief Returns a reference to the object pointed to. * \brief Returns a reference to the object pointed to.
@@ -725,86 +736,95 @@ namespace BlackMisc
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator &operator ++() { Q_ASSERT(m_pimpl); ++*pimpl(); return *this; } RandomAccessIterator &operator ++() { Q_ASSERT(m_pimpl); ++*pimpl(); return *this; }
/*! /*!
* \brief Postfix increment operator advances the iterator. * \brief Postfix increment operator advances the iterator.
* \return Copy of the iterator in the old position. * \return Copy of the iterator in the old position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator ++(int) { Q_ASSERT(m_pimpl); auto copy = *this; ++*pimpl(); return copy; } RandomAccessIterator operator ++(int) { Q_ASSERT(m_pimpl); auto copy = *this; ++*pimpl(); return copy; }
/*! /*!
* \brief Prefix decrement operator backtracks the iterator. * \brief Prefix decrement operator backtracks the iterator.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator &operator --() { Q_ASSERT(m_pimpl); --*pimpl(); return *this; } RandomAccessIterator &operator --() { Q_ASSERT(m_pimpl); --*pimpl(); return *this; }
/*! /*!
* \brief Postfix decrement operator backtracks the iterator. * \brief Postfix decrement operator backtracks the iterator.
* \return Copy of the iterator at the old position. * \return Copy of the iterator at the old position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator --(int) { Q_ASSERT(m_pimpl); auto copy = *this; --*pimpl(); return copy; } RandomAccessIterator operator --(int) { Q_ASSERT(m_pimpl); auto copy = *this; --*pimpl(); return copy; }
/*! /*!
* \brief Advance the iterator by a certain amount. * \brief Advance the iterator by a certain amount.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator +=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() += n; return *this; } RandomAccessIterator operator +=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() += n; return *this; }
/*! /*!
* \brief Advance the iterator by a certain amount. * \brief Advance the iterator by a certain amount.
* \return Copy of the iterator in its new position. * \return Copy of the iterator in its new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator +(difference_type n) const { auto copy = *this; return copy += n; } //! @{
friend RandomAccessIterator operator +(const RandomAccessIterator &i, difference_type n) { auto copy = i; return copy += n; }
friend RandomAccessIterator operator +(difference_type n, const RandomAccessIterator &i) { auto copy = i; return copy += n; }
//! @}
/*! /*!
* \brief Backtrack the iterator by a certain amount. * \brief Backtrack the iterator by a certain amount.
* \return Reference to the iterator at the new position. * \return Reference to the iterator at the new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator -=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() -= n; return *this; } RandomAccessIterator operator -=(difference_type n) { Q_ASSERT(m_pimpl); *pimpl() -= n; return *this; }
/*! /*!
* \brief Backtrack the iterator by a certain amount. * \brief Backtrack the iterator by a certain amount.
* \return Copy of the iterator in its new position. * \return Copy of the iterator in its new position.
* \pre The iterator must be initialized and valid. * \pre The iterator must be initialized and valid.
*/ */
BidirectionalIterator operator -(difference_type n) const { auto copy = *this; return copy -= n; } RandomAccessIterator operator -(difference_type n) const { auto copy = *this; return copy -= n; }
/*! /*!
* \brief Return the distance between two iterators. * \brief Return the distance between two iterators.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
difference_type operator -(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); } difference_type operator -(const RandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); }
/*! /*!
* \brief Test for equality. * \brief Test for equality.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
bool operator ==(const BidirectionalIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); } bool operator ==(const RandomAccessIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); }
/*! /*!
* \brief Test for inequality. * \brief Test for inequality.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
bool operator !=(const BidirectionalIterator &other) const { return !(*this == other); } bool operator !=(const RandomAccessIterator &other) const { return !(*this == other); }
/*! /*!
* \brief For sorting. * \brief For sorting.
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend. * \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
*/ */
//! @{ //! @{
bool operator <(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); } bool operator <(const RandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); }
bool operator >(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() > *other.pimpl(); } bool operator >(const RandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() > *other.pimpl(); }
bool operator <=(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() <= *other.pimpl(); } bool operator <=(const RandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() <= *other.pimpl(); }
bool operator >=(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() >= *other.pimpl(); } bool operator >=(const RandomAccessIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() >= *other.pimpl(); }
//! @} //! @}
/*!
* \brief Subscript operator.
* \pre `(*this + n)` must be dereferenceable.
*/
reference operator [](difference_type n) const { return *(*this + n); }
/*! /*!
* \brief Return opaque pointer to underlying implementation iterator object. * \brief Return opaque pointer to underlying implementation iterator object.
* \pre The iterator must have been initialized. * \pre The iterator must have been initialized.
@@ -837,7 +857,9 @@ namespace BlackMisc
{ {
public: public:
static_assert(std::is_same<T, typename std::iterator_traits<I>::value_type>::value, static_assert(std::is_same<T, typename std::iterator_traits<I>::value_type>::value,
"BidirectionalIterator must be initialized from an iterator with the same value_type."); "RandomAccessIterator must be initialized from an iterator with the same value_type.");
static_assert(std::is_same<typename std::iterator_traits<I>::iterator_category, std::random_access_iterator_tag>::value,
"RandomAccessIterator must be initialized from a random access iterator.");
Pimpl(I &&i) : m_impl(std::move(i)) {} Pimpl(I &&i) : m_impl(std::move(i)) {}
virtual PimplBase *clone() const override { return new Pimpl(*this); } virtual PimplBase *clone() const override { return new Pimpl(*this); }
virtual const_reference operator *() const override { return *m_impl; } virtual const_reference operator *() const override { return *m_impl; }
@@ -861,7 +883,7 @@ namespace BlackMisc
using PimplPtr = QScopedPointer<PimplBase>; using PimplPtr = QScopedPointer<PimplBase>;
PimplPtr m_pimpl; PimplPtr m_pimpl;
explicit BidirectionalIterator(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl() explicit RandomAccessIterator(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl()
// using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const // using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const
PimplBase *pimpl() { return m_pimpl.data(); } PimplBase *pimpl() { return m_pimpl.data(); }

View File

@@ -34,7 +34,7 @@ namespace BlackMisc
*/ */
template <class T> template <class T>
class CSequence : class CSequence :
public CContainerBase<CSequence, T, Iterators::ConstBidirectionalIterator<T>>, public CContainerBase<CSequence, T, Iterators::ConstRandomAccessIterator<T>>,
public Mixin::Icon<CSequence<T>> public Mixin::Icon<CSequence<T>>
{ {
public: public:
@@ -46,8 +46,8 @@ namespace BlackMisc
typedef const T &const_reference; typedef const T &const_reference;
typedef T *pointer; typedef T *pointer;
typedef const T *const_pointer; typedef const T *const_pointer;
typedef typename Iterators::ConstBidirectionalIterator<T> const_iterator; typedef typename Iterators::ConstRandomAccessIterator<T> const_iterator;
typedef typename Iterators::BidirectionalIterator<T> iterator; typedef typename Iterators::RandomAccessIterator<T> iterator;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
typedef intptr_t size_type; typedef intptr_t size_type;
//! @} //! @}