BAN: Cleanup Vector code
*Applies to last patch also!* Remove duplicate code in iterators. We used to have separate iterator and const_iterator but now they are the same class with some enable_if magic to disable references from const_iterator This introduces some 'bad things' you can for example call const_iterator.operator*<false>() to obtain non const reference. I don't think this matters since you could use const_cast or something else to work around const if you really tried
This commit is contained in:
parent
08dfb0e1db
commit
338771c5b0
|
@ -8,48 +8,8 @@
|
||||||
namespace BAN
|
namespace BAN
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, bool CONST>
|
||||||
class Vector;
|
class VectorIterator;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class VectorIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VectorIterator() = default;
|
|
||||||
VectorIterator(const VectorIterator& other) : m_data(other.m_data) { }
|
|
||||||
VectorIterator& operator=(const VectorIterator& other) { m_data = other.m_data; return *this; }
|
|
||||||
VectorIterator& operator++() { m_data++; return *this; }
|
|
||||||
T& operator*() { return *m_data; }
|
|
||||||
const T& operator*() const { return *m_data; }
|
|
||||||
T* operator->() { return m_data; }
|
|
||||||
const T* operator->() const { return m_data; }
|
|
||||||
bool operator==(const VectorIterator<T>& other) const { return !(*this != other); }
|
|
||||||
bool operator!=(const VectorIterator<T>& other) const { return m_data != other.m_data; }
|
|
||||||
private:
|
|
||||||
VectorIterator(T* data) : m_data(data) { }
|
|
||||||
private:
|
|
||||||
T* m_data = nullptr;
|
|
||||||
friend class Vector<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class VectorConstIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VectorConstIterator() = default;
|
|
||||||
VectorConstIterator(const VectorConstIterator& other) : m_data(other.m_data) { }
|
|
||||||
VectorConstIterator& operator=(const VectorConstIterator& other) { m_data = other.m_data; return *this; }
|
|
||||||
VectorConstIterator& operator++() { m_data++; return *this; }
|
|
||||||
const T& operator*() const { return *m_data; }
|
|
||||||
const T* operator->() const { return m_data; }
|
|
||||||
bool operator==(const VectorConstIterator<T>& other) const { return !(*this != other); }
|
|
||||||
bool operator!=(const VectorConstIterator<T>& other) const { return m_data != other.m_data; }
|
|
||||||
private:
|
|
||||||
VectorConstIterator(T* data) : m_data(data) { }
|
|
||||||
private:
|
|
||||||
const T* m_data = nullptr;
|
|
||||||
friend class Vector<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// T must be move assignable, move constructable (and copy constructable for some functions)
|
// T must be move assignable, move constructable (and copy constructable for some functions)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -58,8 +18,8 @@ namespace BAN
|
||||||
public:
|
public:
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using iterator = VectorIterator<T>;
|
using iterator = VectorIterator<T, false>;
|
||||||
using const_iterator = VectorConstIterator<T>;
|
using const_iterator = VectorIterator<T, true>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Vector() = default;
|
Vector() = default;
|
||||||
|
@ -79,16 +39,16 @@ namespace BAN
|
||||||
[[nodiscard]] ErrorOr<void> insert(size_type, T&&);
|
[[nodiscard]] ErrorOr<void> insert(size_type, T&&);
|
||||||
[[nodiscard]] ErrorOr<void> insert(size_type, const T&);
|
[[nodiscard]] ErrorOr<void> insert(size_type, const T&);
|
||||||
|
|
||||||
iterator begin();
|
iterator begin() { return iterator(address_of(0)); }
|
||||||
iterator end();
|
const_iterator begin() const { return const_iterator(address_of(0)); }
|
||||||
const_iterator begin() const;
|
iterator end() { return iterator(address_of(m_size)); }
|
||||||
const_iterator end() const;
|
const_iterator end() const { return const_iterator(address_of(m_size)); }
|
||||||
|
|
||||||
void pop_back();
|
void pop_back();
|
||||||
void remove(size_type);
|
void remove(size_type);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
bool has(const T&) const;
|
bool contains(const T&) const;
|
||||||
|
|
||||||
const T& operator[](size_type) const;
|
const T& operator[](size_type) const;
|
||||||
T& operator[](size_type);
|
T& operator[](size_type);
|
||||||
|
@ -116,6 +76,48 @@ namespace BAN
|
||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, bool CONST>
|
||||||
|
class VectorIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VectorIterator() = default;
|
||||||
|
template<bool C>
|
||||||
|
VectorIterator(const VectorIterator<T, C>& other, enable_if_t<C == CONST || !C>)
|
||||||
|
: m_data(other.m_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorIterator<T, CONST>& operator++() { m_data++; return *this; }
|
||||||
|
VectorIterator<T, CONST>& operator--() { m_data--; return *this; }
|
||||||
|
VectorIterator<T, CONST> operator++(int) { auto temp = *this; ++(*this); return temp; }
|
||||||
|
VectorIterator<T, CONST> operator--(int) { auto temp = *this; --(*this); return temp; }
|
||||||
|
|
||||||
|
template<bool ENABLE = !CONST>
|
||||||
|
enable_if_t<ENABLE, T&> operator*() { ASSERT(m_data); return *m_data; }
|
||||||
|
const T& operator*() const { ASSERT(m_data); return *m_data; }
|
||||||
|
|
||||||
|
template<bool ENABLE = !CONST>
|
||||||
|
enable_if_t<ENABLE, T*> operator->() { ASSERT(m_data); return m_data; }
|
||||||
|
const T* operator->() const { ASSERT(m_data); return m_data; }
|
||||||
|
|
||||||
|
bool operator==(const VectorIterator<T, CONST>& other) const { return m_data == other.m_data; }
|
||||||
|
bool operator!=(const VectorIterator<T, CONST>& other) const { return !(*this == other); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
VectorIterator(T* data) : m_data(data) { }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* m_data = nullptr;
|
||||||
|
|
||||||
|
friend class Vector<T>;
|
||||||
|
friend class VectorIterator<T, !CONST>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T>::Vector(Vector<T>&& other)
|
Vector<T>::Vector(Vector<T>&& other)
|
||||||
{
|
{
|
||||||
|
@ -242,30 +244,6 @@ namespace BAN
|
||||||
return insert(move(T(value)), index);
|
return insert(move(T(value)), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename Vector<T>::iterator Vector<T>::begin()
|
|
||||||
{
|
|
||||||
return VectorIterator<T>(address_of(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename Vector<T>::iterator Vector<T>::end()
|
|
||||||
{
|
|
||||||
return VectorIterator<T>(address_of(m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename Vector<T>::const_iterator Vector<T>::begin() const
|
|
||||||
{
|
|
||||||
return VectorConstIterator<T>(address_of(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename Vector<T>::const_iterator Vector<T>::end() const
|
|
||||||
{
|
|
||||||
return VectorConstIterator<T>(address_of(m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Vector<T>::pop_back()
|
void Vector<T>::pop_back()
|
||||||
{
|
{
|
||||||
|
@ -296,7 +274,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool Vector<T>::has(const T& other) const
|
bool Vector<T>::contains(const T& other) const
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
if (*address_of(i) == other)
|
if (*address_of(i) == other)
|
||||||
|
|
Loading…
Reference in New Issue