- Documentation of containers and adjusting page hierarchy

This commit is contained in:
2025-08-18 14:13:35 -04:00
parent 27754a56d7
commit 55a8c54119
28 changed files with 934 additions and 313 deletions

View File

@@ -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) {