- Documentation of containers and adjusting page hierarchy
This commit is contained in:
@@ -26,15 +26,40 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief Data structure defining a double-ended queue.
|
||||
///
|
||||
/// \details
|
||||
/// This behaves the similar to fennec::list, however it does not allow arbitrary access, insertion, or deletion.
|
||||
/// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change.
|
||||
///
|
||||
/// | Property | Value |
|
||||
/// |:----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogenous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
///
|
||||
/// \tparam TypeT value type
|
||||
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||
struct deque {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
using elem_t = TypeT;
|
||||
using value_t = TypeT;
|
||||
class iterator;
|
||||
|
||||
private:
|
||||
struct node {
|
||||
elem_t value;
|
||||
value_t value;
|
||||
node *prev, *next;
|
||||
|
||||
template<typename...ArgsT>
|
||||
@@ -46,11 +71,18 @@ public:
|
||||
~node() = default;
|
||||
};
|
||||
|
||||
public:
|
||||
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
||||
using elem_t = node*;
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
/// \name Constructors & Destructor
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes an empty deque
|
||||
deque()
|
||||
: _alloc()
|
||||
, _first(nullptr)
|
||||
@@ -58,6 +90,24 @@ public:
|
||||
, _size(0) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor
|
||||
/// \param deque the deque to copy
|
||||
deque(const deque& deque)
|
||||
: _alloc(deque._alloc)
|
||||
, _first(nullptr)
|
||||
, _last(nullptr)
|
||||
, _size(0) {
|
||||
const elem_t node = deque._first;
|
||||
while (node) {
|
||||
this->push_back(node->value);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Deque Move Constructor
|
||||
/// \param deque the deque to move
|
||||
deque(deque&& deque) noexcept
|
||||
: _alloc(deque._alloc)
|
||||
, _first(deque._first)
|
||||
@@ -67,69 +117,128 @@ public:
|
||||
deque._last = nullptr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Destructor, calls deque::clear
|
||||
~deque() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
bool empty() const {
|
||||
/// \name Properties
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns `true` when the deque is empty, `false` otherwise
|
||||
constexpr bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
///
|
||||
/// \returns the number of elements in size()
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
elem_t& front() {
|
||||
/// \name Access
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns a reference to the first element in the deque
|
||||
value_t& front() {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _first->value;
|
||||
}
|
||||
|
||||
elem_t& back() {
|
||||
///
|
||||
/// \returns a const-qualified reference to the first element in the deque
|
||||
const value_t& front() const {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _first->value;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns a reference to the last element in the deque
|
||||
value_t& back() {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _last->value;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns a const-qualified reference to the last element in the deque
|
||||
const value_t& back() const {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _last->value;
|
||||
}
|
||||
|
||||
// Insertion ===========================================================================================================
|
||||
/// @}
|
||||
|
||||
void push_front(elem_t&& elem) {
|
||||
|
||||
// Modifiers ===========================================================================================================
|
||||
|
||||
/// \name Modifiers
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Push Front Move, moves a value to the front of the deque
|
||||
/// \param elem the value to move
|
||||
void push_front(value_t&& elem) {
|
||||
this->_push_front(elem);
|
||||
}
|
||||
|
||||
void push_front(const elem_t& elem) {
|
||||
///
|
||||
/// \brief Push Front Copy, copies a value to the front of the deque
|
||||
/// \param elem the value to copy
|
||||
void push_front(const value_t& elem) {
|
||||
this->_push_front(elem);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Emplace Front, constructs a new value at the front of the deque
|
||||
/// \tparam ArgsT Argument types
|
||||
/// \param args Arguments used to construct the value
|
||||
template<typename...ArgsT>
|
||||
void emplace_front(ArgsT&&...args) {
|
||||
this->_push_front(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
void push_back(elem_t&& elem) {
|
||||
|
||||
///
|
||||
/// \brief Push Back Move, moves a value to the back of the deque
|
||||
/// \param elem the value to move
|
||||
void push_back(value_t&& elem) {
|
||||
this->_push_back(elem);
|
||||
}
|
||||
|
||||
void push_back(const elem_t& elem) {
|
||||
///
|
||||
/// \brief Push Back Copy, copies a value to the back of the deque
|
||||
/// \param elem the value to copy
|
||||
void push_back(const value_t& elem) {
|
||||
this->_push_back(elem);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Emplace Back, constructs a new value at the back of the deque
|
||||
/// \tparam ArgsT Argument types
|
||||
/// \param args Arguments used to construct the value
|
||||
template<typename...ArgsT>
|
||||
void emplace_back(ArgsT&&...args) {
|
||||
this->_push_back(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
|
||||
// Deletion ============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Clears the contents of the deque
|
||||
void clear() {
|
||||
node* it = _first;
|
||||
elem_t it = _first;
|
||||
while (it) {
|
||||
node* next = it->next;
|
||||
elem_t next = it->next;
|
||||
fennec::destruct(it);
|
||||
_alloc.deallocate(it);
|
||||
it = next;
|
||||
@@ -139,11 +248,13 @@ public:
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Erase the First Element
|
||||
void pop_front() {
|
||||
if (_first == nullptr) {
|
||||
return;
|
||||
}
|
||||
node* next = _first->next;
|
||||
elem_t next = _first->next;
|
||||
fennec::destruct(_first);
|
||||
_alloc.deallocate(_first);
|
||||
_first = next;
|
||||
@@ -151,11 +262,13 @@ public:
|
||||
--_size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Erase the Last Element
|
||||
void pop_back() {
|
||||
if (_last == nullptr) {
|
||||
return;
|
||||
}
|
||||
node* prev = _last->prev;
|
||||
elem_t prev = _last->prev;
|
||||
fennec::destruct(_last);
|
||||
_alloc.deallocate(_last);
|
||||
_last = prev;
|
||||
@@ -163,6 +276,15 @@ public:
|
||||
--_size;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Iteration ===========================================================================================================
|
||||
|
||||
/*
|
||||
* TODO: Decide whether you should be able to iterate over a deque
|
||||
*/
|
||||
|
||||
private:
|
||||
alloc_t _alloc;
|
||||
node *_first, *_last;
|
||||
@@ -170,7 +292,7 @@ private:
|
||||
|
||||
template<typename...ArgsT>
|
||||
void _push_front(ArgsT&&...args) {
|
||||
node* next = _first;
|
||||
elem_t next = _first;
|
||||
_first = _alloc.allocate(1);
|
||||
fennec::construct(_first, nullptr, next, fennec::forward<ArgsT>(args)...);
|
||||
if (next) {
|
||||
@@ -183,7 +305,7 @@ private:
|
||||
|
||||
template<typename...ArgsT>
|
||||
void _push_back(ArgsT&&...args) {
|
||||
node* prev = _last;
|
||||
elem_t prev = _last;
|
||||
_last = _alloc.allocate(1);
|
||||
fennec::construct(_last, prev, nullptr, fennec::forward<ArgsT>(args)...);
|
||||
if (prev) {
|
||||
|
||||
Reference in New Issue
Block a user