107 lines
3.5 KiB
C++
107 lines
3.5 KiB
C++
#ifndef INCLUDED_TRNX_VECTOR_IMPL
|
|
#define INCLUDED_TRNX_VECTOR_IMPL
|
|
|
|
#include <cstddef>
|
|
#include <exception>
|
|
#include <iterator>
|
|
#include <type_traits>
|
|
|
|
namespace trnx {
|
|
namespace detail {
|
|
|
|
// This union is not meant to be shown/completely understood from the students.
|
|
//
|
|
// They should know that `uninitialized<T>` means "enough storage for a `T`
|
|
// instance, and that they can manually control the lifetime of that instance
|
|
// through the `.construct` and `.destroy` member functions.
|
|
//
|
|
// It is undefined behavior to:
|
|
// * Call `construct` on an already-initialized instance.
|
|
// * Call `destroy` on a non-initialized instance.
|
|
// * Access the reference returned by `get` on a non-initialized instance.
|
|
//
|
|
template <typename T>
|
|
union uninitialized
|
|
{
|
|
private:
|
|
T d_datum;
|
|
|
|
public:
|
|
using inner_type = T;
|
|
|
|
uninitialized() { }
|
|
~uninitialized() { }
|
|
|
|
template <typename... Ts>
|
|
void construct(Ts&&... xs)
|
|
{
|
|
new (&d_datum) T(std::forward<Ts>(xs)...);
|
|
}
|
|
|
|
void destroy()
|
|
{
|
|
d_datum.~T();
|
|
}
|
|
|
|
T& get() { return d_datum; }
|
|
const T& get() const { return d_datum; }
|
|
};
|
|
|
|
// This class is not meant to be shown/completely understood from the students.
|
|
//
|
|
// It basically unwraps `uninitialized<T>` upon dereference, behaving as any
|
|
// other normal random access iterator, transparently to the user.
|
|
//
|
|
template <typename T>
|
|
class iter_impl
|
|
{
|
|
private:
|
|
T* d_ptr;
|
|
using inner_type = typename T::inner_type;
|
|
|
|
public:
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = inner_type;
|
|
using pointer = inner_type*;
|
|
using reference = inner_type&;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
iter_impl() : d_ptr(nullptr) { }
|
|
iter_impl(T* rhs) : d_ptr(rhs) { }
|
|
|
|
iter_impl(const iter_impl& rhs) : d_ptr(rhs.d_ptr) { }
|
|
iter_impl& operator=(const iter_impl &rhs) { d_ptr = rhs.d_ptr; return *this; }
|
|
|
|
iter_impl& operator+=(difference_type rhs) { d_ptr += rhs; return *this; }
|
|
iter_impl& operator-=(difference_type rhs) { d_ptr -= rhs; return *this; }
|
|
|
|
inner_type& operator*() const { return d_ptr->get(); }
|
|
inner_type* operator->() const { return &d_ptr->get(); }
|
|
inner_type& operator[](difference_type rhs) const { return d_ptr[rhs]; }
|
|
|
|
iter_impl& operator++() { ++d_ptr; return *this; }
|
|
iter_impl& operator--() { --d_ptr; return *this; }
|
|
|
|
iter_impl operator++(int) { iter_impl tmp(*this); ++d_ptr; return tmp; }
|
|
iter_impl operator--(int) { iter_impl tmp(*this); --d_ptr; return tmp; }
|
|
|
|
difference_type operator-(const iter_impl& rhs) const { return iter_impl(d_ptr - rhs.ptr); }
|
|
|
|
iter_impl operator+(difference_type rhs) const { return iter_impl(d_ptr + rhs); }
|
|
iter_impl operator-(difference_type rhs) const { return iter_impl(d_ptr - rhs); }
|
|
friend iter_impl operator+(difference_type lhs, const iter_impl& rhs) { return iter_impl(lhs + rhs.d_ptr); }
|
|
friend iter_impl operator-(difference_type lhs, const iter_impl& rhs) { return iter_impl(lhs - rhs.d_ptr); }
|
|
|
|
bool operator==(const iter_impl& rhs) const { return d_ptr == rhs.d_ptr; }
|
|
bool operator!=(const iter_impl& rhs) const { return d_ptr != rhs.d_ptr; }
|
|
bool operator>(const iter_impl& rhs) const { return d_ptr > rhs.d_ptr; }
|
|
bool operator<(const iter_impl& rhs) const { return d_ptr < rhs.d_ptr; }
|
|
bool operator>=(const iter_impl& rhs) const { return d_ptr >= rhs.d_ptr; }
|
|
bool operator<=(const iter_impl& rhs) const { return d_ptr <= rhs.d_ptr; }
|
|
};
|
|
|
|
} // close namespace detail
|
|
} // close namespace trnx
|
|
|
|
#endif
|