wpiutil UidVector: Implement clear() and forward iterator (#1293)

The forward iterator only iterates over "live" elements.

Also add a couple of unit tests for UidVector.
This commit is contained in:
Peter Johnson
2018-08-24 20:39:57 -07:00
committed by GitHub
parent 8d91343bf5
commit d6d5321828
2 changed files with 131 additions and 1 deletions

View File

@@ -8,11 +8,59 @@
#ifndef WPIUTIL_WPI_UIDVECTOR_H_
#define WPIUTIL_WPI_UIDVECTOR_H_
#include <iterator>
#include <utility>
#include <vector>
namespace wpi {
namespace impl {
template <typename It>
class UidVectorIterator {
public:
using iterator_type = std::forward_iterator_tag;
using value_type = typename It::value_type;
using difference_type = typename It::difference_type;
using reference = typename It::reference;
using pointer = typename It::pointer;
UidVectorIterator() = default;
explicit UidVectorIterator(It it, It end) : m_it(it), m_end(end) {
// advance to first non-empty element
while (m_it != m_end && !*m_it) ++m_it;
}
reference operator*() const noexcept { return *m_it; }
pointer operator->() const noexcept { return m_it.operator->(); }
UidVectorIterator& operator++() noexcept {
// advance past empty elements
do {
++m_it;
} while (m_it != m_end && !*m_it);
return *this;
}
UidVectorIterator operator++(int)noexcept {
UidVectorIterator it = *this;
++it;
return it;
}
bool operator==(const UidVectorIterator& oth) const noexcept {
return m_it == oth.m_it;
}
bool operator!=(const UidVectorIterator& oth) const noexcept {
return m_it != oth.m_it;
}
private:
It m_it;
It m_end;
};
} // namespace impl
// Vector which provides an integrated freelist for removal and reuse of
// individual elements.
// @tparam T element type; must be default-constructible and evaluate in
@@ -22,7 +70,16 @@ namespace wpi {
template <typename T, typename std::vector<T>::size_type reuse_threshold>
class UidVector {
public:
typedef typename std::vector<T>::size_type size_type;
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = typename std::vector<T>::size_type;
using difference_type = typename std::vector<T>::difference_type;
using iterator = impl::UidVectorIterator<typename std::vector<T>::iterator>;
using const_iterator =
impl::UidVectorIterator<typename std::vector<T>::const_iterator>;
bool empty() const { return m_active_count == 0; }
size_type size() const { return m_vector.size(); }
@@ -56,6 +113,31 @@ class UidVector {
--m_active_count;
}
// Removes all elements.
void clear() {
m_vector.clear();
m_free.clear();
m_active_count = 0;
}
// Iterator access
iterator begin() noexcept {
return iterator(m_vector.begin(), m_vector.end());
}
const_iterator begin() const noexcept {
return const_iterator(m_vector.begin(), m_vector.end());
}
const_iterator cbegin() const noexcept {
return const_iterator(m_vector.begin(), m_vector.end());
}
iterator end() noexcept { return iterator(m_vector.end(), m_vector.end()); }
const_iterator end() const noexcept {
return const_iterator(m_vector.end(), m_vector.end());
}
const_iterator cend() const noexcept {
return const_iterator(m_vector.end(), m_vector.end());
}
private:
std::vector<T> m_vector;
std::vector<size_type> m_free;