- Documentation of containers, core, and format
This commit is contained in:
@@ -260,7 +260,7 @@ INHERIT_DOCS = YES
|
|||||||
# of the file/class/namespace that contains it.
|
# of the file/class/namespace that contains it.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
SEPARATE_MEMBER_PAGES = NO
|
SEPARATE_MEMBER_PAGES = YES
|
||||||
|
|
||||||
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
|
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
|
||||||
# uses this value to replace tabs by spaces in code fragments.
|
# uses this value to replace tabs by spaces in code fragments.
|
||||||
@@ -944,7 +944,6 @@ WARN_LOGFILE =
|
|||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = "@PROJECT_SOURCE_DIR@/include" \
|
INPUT = "@PROJECT_SOURCE_DIR@/include" \
|
||||||
"@PROJECT_SOURCE_DIR@/source" \
|
|
||||||
"@PROJECT_SOURCE_DIR@/README.md"
|
"@PROJECT_SOURCE_DIR@/README.md"
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
@@ -1050,6 +1049,7 @@ RECURSIVE = YES
|
|||||||
# run.
|
# run.
|
||||||
|
|
||||||
EXCLUDE = "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/lib" \
|
EXCLUDE = "@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/lib" \
|
||||||
|
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/wayland/libdecor" \
|
||||||
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/xkb/lib"
|
"@PROJECT_SOURCE_DIR@/include/fennec/platform/linux/xkb/lib"
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||||
@@ -2511,7 +2511,7 @@ EXTERNAL_PAGES = YES
|
|||||||
# and usage relations if the target is undocumented or is not a class.
|
# and usage relations if the target is undocumented or is not a class.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
HIDE_UNDOC_RELATIONS = YES
|
HIDE_UNDOC_RELATIONS = NO
|
||||||
|
|
||||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||||
# available from the path. This tool is part of Graphviz (see:
|
# available from the path. This tool is part of Graphviz (see:
|
||||||
|
|||||||
@@ -44,17 +44,17 @@ namespace fennec
|
|||||||
/// \brief Data Structure that defines a compile-time allocated array
|
/// \brief Data Structure that defines a compile-time allocated array
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
/// |:----------:|:----------:|
|
/// |:----------:|:-----------:|
|
||||||
/// | stable | ✅ |
|
/// | stable | ✅ |
|
||||||
/// | dynamic | ⛔ |
|
/// | dynamic | ⛔ |
|
||||||
/// | homogenous | ✅ |
|
/// | homogenous | ✅ |
|
||||||
/// | distinct | ⛔ |
|
/// | distinct | ⛔ |
|
||||||
/// | ordered | ⛔ |
|
/// | ordered | ⛔ |
|
||||||
/// | space | \f$O(N)\f$ |
|
/// | space | \f$O(N)\f$ |
|
||||||
/// | linear | ✅ |
|
/// | linear | ✅ |
|
||||||
/// | access | \f$O(1)\f$ |
|
/// | access | \f$O(1)\f$ |
|
||||||
/// | find | \f$O(N)\f$ |
|
/// | find | \f$O(N)\f$ |
|
||||||
/// | insertion | ⛔ |
|
/// | insertion | ⛔ |
|
||||||
/// | deletion | ⛔ |
|
/// | deletion | ⛔ |
|
||||||
///
|
///
|
||||||
@@ -65,7 +65,7 @@ struct array {
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = ValueT; ///< Alias for `ValueT`
|
using value_t = ValueT; ///< Alias for \f$ValueT\f$
|
||||||
|
|
||||||
// Public Members ======================================================================================================
|
// Public Members ======================================================================================================
|
||||||
|
|
||||||
@@ -105,7 +105,15 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \copydetails array::operator[](size_t) const
|
/// \details Returns a reference to the element at \c i
|
||||||
|
/// \param i index of the element to return
|
||||||
|
/// \return reference to the requested element
|
||||||
|
///
|
||||||
|
/// \par Time-Complexity
|
||||||
|
/// Constant
|
||||||
|
///
|
||||||
|
/// \par Space-Complexity
|
||||||
|
/// Constant
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assertd(i < ElemV, "Array Out of Bounds");
|
assertd(i < ElemV, "Array Out of Bounds");
|
||||||
return data[i];
|
return data[i];
|
||||||
@@ -219,7 +227,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
template<size_t...i>
|
template<size_t...i>
|
||||||
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {
|
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {
|
||||||
return ((lhs[i] == rhs[i]) && ...);
|
return ((lhs[i] == rhs[i]) and ...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -48,18 +48,18 @@ template<typename TypeT, class AllocT = allocator<TypeT>>
|
|||||||
struct bintree {
|
struct bintree {
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
protected:
|
private:
|
||||||
struct node;
|
struct node;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT; //!< The element type
|
||||||
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The allocator type
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1; //!< null position constant
|
||||||
|
|
||||||
friend class iterator;
|
friend class iterator;
|
||||||
friend class const_iterator;
|
friend class const_iterator;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
struct node {
|
struct node {
|
||||||
value_t value;
|
value_t value;
|
||||||
size_t parent;
|
size_t parent;
|
||||||
@@ -144,7 +144,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no elements in the tree, `false` otherwise.
|
/// \returns \f$true\f$ when there are no elements in the tree, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The next id to be returned by `insert` or `emplace`.
|
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
|
||||||
constexpr size_t next_id() const {
|
constexpr size_t next_id() const {
|
||||||
size_t i = _size;
|
size_t i = _size;
|
||||||
if (not _freed.empty()) {
|
if (not _freed.empty()) {
|
||||||
@@ -166,7 +166,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The next id to be returned by `insert` or `emplace`.
|
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
|
||||||
constexpr size_t root() const {
|
constexpr size_t root() const {
|
||||||
return _root;
|
return _root;
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The parent of node `i`
|
/// \returns The parent of node \f$i\f$
|
||||||
constexpr size_t parent(size_t i) const {
|
constexpr size_t parent(size_t i) const {
|
||||||
return i == npos ? npos : _table[i].parent;
|
return i == npos ? npos : _table[i].parent;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The grandparent of node `i`
|
/// \returns The grandparent of node \f$i\f$
|
||||||
constexpr size_t grandparent(size_t i) const {
|
constexpr size_t grandparent(size_t i) const {
|
||||||
return parent(parent(i));
|
return parent(parent(i));
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The left child of node `i`
|
/// \returns The left child of node \f$i\f$
|
||||||
constexpr size_t left(size_t i) const {
|
constexpr size_t left(size_t i) const {
|
||||||
return i == npos ? npos : _table[i].child[false];
|
return i == npos ? npos : _table[i].child[false];
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The right child of node `i`
|
/// \returns The right child of node \f$i\f$
|
||||||
constexpr size_t right(size_t i) const {
|
constexpr size_t right(size_t i) const {
|
||||||
return i == npos ? npos : _table[i].child[true];
|
return i == npos ? npos : _table[i].child[true];
|
||||||
}
|
}
|
||||||
@@ -214,8 +214,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \param dir The direction to go `true` for right, `false` for left
|
/// \param dir The direction to go \f$true\f$ for right, \f$false\f$ for left
|
||||||
/// \returns The child in the direction specified by `dir`
|
/// \returns The child in the direction specified by \f$dir\f$
|
||||||
constexpr size_t child(size_t i, bool dir) const {
|
constexpr size_t child(size_t i, bool dir) const {
|
||||||
return i == npos ? npos : _table[i].child[dir];
|
return i == npos ? npos : _table[i].child[dir];
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns `true` if `i` is the right node of `parent(i)`, `false` otherwise
|
/// \returns \f$true\f$ if \f$i\f$ is the right node of `parent(i)`, \f$false\f$ otherwise
|
||||||
constexpr bool direction(size_t i) const {
|
constexpr bool direction(size_t i) const {
|
||||||
return i == npos ? false : i == right(_parent(i));
|
return i == npos ? false : i == right(_parent(i));
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief \f$O(1)\f$
|
/// \brief \f$O(1)\f$
|
||||||
/// \param i The id of the node
|
/// \param i The id of the node
|
||||||
/// \returns The id of the sibling of `i`
|
/// \returns The id of the sibling of \f$i\f$
|
||||||
constexpr size_t sibling(size_t i) const {
|
constexpr size_t sibling(size_t i) const {
|
||||||
if (i == npos) {
|
if (i == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -247,7 +247,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(\log n)\f$
|
/// \details \f$O(\log n)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The depth of node `i`
|
/// \returns The depth of node \f$i\f$
|
||||||
constexpr size_t depth(size_t i) const {
|
constexpr size_t depth(size_t i) const {
|
||||||
size_t d = 0;
|
size_t d = 0;
|
||||||
while (i != npos) {
|
while (i != npos) {
|
||||||
@@ -260,7 +260,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief \f$O(\log n)\f$
|
/// \brief \f$O(\log n)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The id of the left-most node of `i`
|
/// \returns The id of the left-most node of \f$i\f$
|
||||||
constexpr size_t left_most(size_t i) const {
|
constexpr size_t left_most(size_t i) const {
|
||||||
if (i >= _table.size()) {
|
if (i >= _table.size()) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -274,7 +274,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief \f$O(\log n)\f$
|
/// \brief \f$O(\log n)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns The id of the right-most node of `i`
|
/// \returns The id of the right-most node of \f$i\f$
|
||||||
constexpr size_t right_most(size_t i) const {
|
constexpr size_t right_most(size_t i) const {
|
||||||
if (i >= _table.size()) {
|
if (i >= _table.size()) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -297,7 +297,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details \f$O(1)\f$
|
/// \details \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assertd(i < _table.size(), "Index out of bounds.");
|
assertd(i < _table.size(), "Index out of bounds.");
|
||||||
return _table[i].value;
|
return _table[i].value;
|
||||||
@@ -306,7 +306,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \details Const Access, \f$O(1)\f$
|
/// \details Const Access, \f$O(1)\f$
|
||||||
/// \param i The node id
|
/// \param i The node id
|
||||||
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assertd(i < _table.size(), "Index out of bounds.");
|
assertd(i < _table.size(), "Index out of bounds.");
|
||||||
return _table[i].value;
|
return _table[i].value;
|
||||||
@@ -320,8 +320,8 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Left Insertion, constructs a new node as the left child of `p`
|
/// \brief Move Left Insertion, constructs a new node as the left child of \f$p\f$
|
||||||
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param val The object to move into the new node
|
/// \param val The object to move into the new node
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -330,8 +330,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Left Insertion, constructs a new node as the left child of `p`
|
/// \brief Copy Left Insertion, constructs a new node as the left child of \f$p\f$
|
||||||
/// \details If the left node of `p` already exists, the copy assignment operator is used instead
|
/// \details If the left node of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param val The object to copy to the new node
|
/// \param val The object to copy to the new node
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -340,8 +340,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Left Insertion, constructs a new node as the left child of `p`
|
/// \brief Emplace Left Insertion, constructs a new node as the left child of \f$p\f$
|
||||||
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param args The arguments to construct the new node with
|
/// \param args The arguments to construct the new node with
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -351,8 +351,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Right Insertion, constructs a new node as the right child of `p`
|
/// \brief Move Right Insertion, constructs a new node as the right child of \f$p\f$
|
||||||
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param val The object to move into the new node
|
/// \param val The object to move into the new node
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -361,8 +361,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Right Insertion, constructs a new node as the right child of `p`
|
/// \brief Copy Right Insertion, constructs a new node as the right child of \f$p\f$
|
||||||
/// \details If the right node of `p` already exists, the copy assignment operator is used instead
|
/// \details If the right node of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param val The object to copy to the new node
|
/// \param val The object to copy to the new node
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -371,8 +371,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Right Insertion, constructs a new node as the right child of `p`
|
/// \brief Emplace Right Insertion, constructs a new node as the right child of \f$p\f$
|
||||||
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param args The arguments to construct the new node with
|
/// \param args The arguments to construct the new node with
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new node
|
||||||
@@ -384,9 +384,9 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Perform a Tree Rotation at `i` in the specified direction
|
/// \brief Perform a Tree Rotation at \f$i\f$ in the specified direction
|
||||||
/// \param sub The root node for the rotation
|
/// \param sub The root node for the rotation
|
||||||
/// \param dir The direction to rotate, `true` for right, `false` for left
|
/// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left
|
||||||
/// \returns the new root
|
/// \returns the new root
|
||||||
constexpr size_t rotate(size_t sub, bool dir) {
|
constexpr size_t rotate(size_t sub, bool dir) {
|
||||||
if (sub == npos) {
|
if (sub == npos) {
|
||||||
@@ -413,8 +413,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Insertion, bool d, constructs a new node as the child of `p`
|
/// \brief Move Insertion, bool d, constructs a new node as the child of \f$p\f$
|
||||||
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param d The direction to insert
|
/// \param d The direction to insert
|
||||||
/// \param val The object to move into the new node
|
/// \param val The object to move into the new node
|
||||||
@@ -424,8 +424,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Insertion, bool d, constructs a new node as the child of `p`
|
/// \brief Copy Insertion, bool d, constructs a new node as the child of \f$p\f$
|
||||||
/// \details If the child of `p` already exists, the copy assignment operator is used instead
|
/// \details If the child of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param d The direction to insert
|
/// \param d The direction to insert
|
||||||
/// \param val The object to copy to the new node
|
/// \param val The object to copy to the new node
|
||||||
@@ -435,8 +435,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Insertion, constructs a new node as the child of `p`
|
/// \brief Emplace Insertion, constructs a new node as the child of \f$p\f$
|
||||||
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
|
||||||
/// \param p The parent node
|
/// \param p The parent node
|
||||||
/// \param d The direction to insert
|
/// \param d The direction to insert
|
||||||
/// \param args The arguments to construct the new node with
|
/// \param args The arguments to construct the new node with
|
||||||
@@ -482,7 +482,7 @@ public:
|
|||||||
/// \brief Traverse the tree using a specified order and visiting functor
|
/// \brief Traverse the tree using a specified order and visiting functor
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// The visitor should accept a reference to a value of type `TypeT` and a `size_t` which contains the node's id.
|
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a `size_t` which contains the node's id.
|
||||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||||
///
|
///
|
||||||
/// \tparam OrderT The order with which to traverse the tree.
|
/// \tparam OrderT The order with which to traverse the tree.
|
||||||
@@ -508,13 +508,21 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Traverser pattern for breadth-first traversal
|
/// \brief Traverser pattern for breadth-first traversal
|
||||||
struct breadth_first {
|
struct breadth_first {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
size_t operator()(const bintree&, size_t start) {
|
size_t operator()(const bintree&, size_t start) {
|
||||||
return head = start;
|
return head = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \param mode The mode specifying branch conditions
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -541,19 +549,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Traverser pattern for pre-order traversal
|
/// \brief Traverser pattern for pre-order traversal
|
||||||
struct pre_order {
|
struct pre_order {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const bintree&, size_t start) {
|
constexpr size_t operator()(const bintree&, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \param mode The mode specifying branch conditions
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -580,19 +600,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Traverser pattern for in-order traversal
|
/// \brief Traverser pattern for in-order traversal
|
||||||
struct in_order {
|
struct in_order {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const bintree& tree, size_t start) {
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -619,33 +651,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Traverser pattern for post-order traversal
|
/// \brief Traverser pattern for post-order traversal
|
||||||
struct post_order {
|
struct post_order {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
constexpr size_t successor(const bintree& tree, size_t n) {
|
|
||||||
size_t s = tree.left_most(n);
|
|
||||||
while (n == s) {
|
|
||||||
size_t r = tree.right(n);
|
|
||||||
if (r != npos) {
|
|
||||||
n = r;
|
|
||||||
s = tree.left_most(n);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s == npos ? n : s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const bintree& tree, size_t start) {
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return this->successor(tree, start);
|
return this->_successor(tree, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -659,7 +689,7 @@ public:
|
|||||||
visit.push_front(parent);
|
visit.push_front(parent);
|
||||||
}
|
}
|
||||||
} else if (pright != npos) {
|
} else if (pright != npos) {
|
||||||
visit.push_front(this->successor(tree, pright));
|
visit.push_front(this->_successor(tree, pright));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not visit.empty()) {
|
if (not visit.empty()) {
|
||||||
@@ -672,23 +702,50 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t _successor(const bintree& tree, size_t n) {
|
||||||
|
size_t s = tree.left_most(n);
|
||||||
|
while (n == s) {
|
||||||
|
size_t r = tree.right(n);
|
||||||
|
if (r != npos) {
|
||||||
|
n = r;
|
||||||
|
s = tree.left_most(n);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s == npos ? n : s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Iterator ============================================================================================================
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
|
/// \details Performs pre-order traversal
|
||||||
class iterator {
|
class iterator {
|
||||||
protected:
|
|
||||||
bintree* _tree;
|
|
||||||
in_order _order;
|
|
||||||
size_t _n;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief bintree iterator constructor
|
||||||
|
/// \param tree A reference to the tree
|
||||||
|
/// \param root The root node for iteration
|
||||||
constexpr iterator(bintree* tree, size_t root)
|
constexpr iterator(bintree* tree, size_t root)
|
||||||
: _tree(tree)
|
: _tree(tree)
|
||||||
, _order()
|
, _order()
|
||||||
, _n(_order(*tree, root)) {
|
, _n(_order(*tree, root)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief bintree iterator constructor
|
||||||
|
/// \param tree A reference to the tree
|
||||||
|
/// \param root The root node for iteration
|
||||||
|
/// \param node The node to jump to
|
||||||
constexpr iterator(bintree* tree, size_t root, size_t node)
|
constexpr iterator(bintree* tree, size_t root, size_t node)
|
||||||
: _tree(tree)
|
: _tree(tree)
|
||||||
, _order()
|
, _order()
|
||||||
@@ -696,42 +753,171 @@ public:
|
|||||||
_order.head = root;
|
_order.head = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The index of the current node
|
||||||
size_t index() const {
|
size_t index() const {
|
||||||
return _n;
|
return _n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator pre-increment operator
|
||||||
|
/// \returns A reference to self after having stepped to the next node
|
||||||
iterator& operator++() {
|
iterator& operator++() {
|
||||||
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns the value held in the current node
|
||||||
value_t& operator*() {
|
value_t& operator*() {
|
||||||
return (*_tree)[_n];
|
return (*_tree)[_n];
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t* operator->() {
|
///
|
||||||
return &(*_tree)[_n];
|
/// \returns the value held in the current node
|
||||||
}
|
|
||||||
|
|
||||||
const value_t& operator*() const {
|
const value_t& operator*() const {
|
||||||
return (*_tree)[_n];
|
return (*_tree)[_n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a reference to the value held in the current node
|
||||||
|
value_t* operator->() {
|
||||||
|
return &(*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns a reference to the value held in the current node
|
||||||
const value_t* operator->() const {
|
const value_t* operator->() const {
|
||||||
return &(*_tree)[_n];
|
return &(*_tree)[_n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if iterators are identical, \f$false\f$ otherwise
|
||||||
constexpr bool operator==(const iterator& it) {
|
constexpr bool operator==(const iterator& it) {
|
||||||
return _tree == it._tree and _n == it._n;
|
return _tree == it._tree and _n == it._n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if iterators are different, \f$false\f$ otherwise
|
||||||
constexpr bool operator!=(const iterator& it) {
|
constexpr bool operator!=(const iterator& it) {
|
||||||
return _tree != it._tree or _n != it._n;
|
return _tree != it._tree or _n != it._n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bintree* _tree;
|
||||||
|
in_order _order;
|
||||||
|
size_t _n;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
|
/// \details Performs pre-order traversal
|
||||||
|
class const_iterator {
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// \brief bintree iterator constructor
|
||||||
|
/// \param tree A reference to the tree
|
||||||
|
/// \param root The root node for iteration
|
||||||
|
constexpr const_iterator(bintree* tree, size_t root)
|
||||||
|
: _tree(tree)
|
||||||
|
, _order()
|
||||||
|
, _n(_order(*tree, root)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief bintree iterator constructor
|
||||||
|
/// \param tree A reference to the tree
|
||||||
|
/// \param root The root node for iteration
|
||||||
|
/// \param node The node to jump to
|
||||||
|
constexpr const_iterator(bintree* tree, size_t root, size_t node)
|
||||||
|
: _tree(tree)
|
||||||
|
, _order()
|
||||||
|
, _n(node) {
|
||||||
|
_order.head = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The index of the current node
|
||||||
|
size_t index() const {
|
||||||
|
return _n;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator pre-increment operator
|
||||||
|
/// \returns A reference to self after having stepped to the next node
|
||||||
|
const_iterator& operator++() {
|
||||||
|
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the value held in the current node
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return (*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns a reference to the value held in the current node
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &(*_tree)[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if iterators are identical, \f$false\f$ otherwise
|
||||||
|
constexpr bool operator==(const iterator& it) {
|
||||||
|
return _tree == it._tree and _n == it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if iterators are different, \f$false\f$ otherwise
|
||||||
|
constexpr bool operator!=(const iterator& it) {
|
||||||
|
return _tree != it._tree or _n != it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bintree* _tree;
|
||||||
|
in_order _order;
|
||||||
|
size_t _n;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns an iterator at the first element in pre-order traversal
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns an iterator at the first element in pre-order traversal
|
||||||
|
const_iterator begin() const {
|
||||||
|
return iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns an iterator at the first element in pre-order traversal
|
||||||
|
iterator end() {
|
||||||
|
return iterator(this, _root, nullid);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns an iterator at the first element in pre-order traversal
|
||||||
|
const_iterator end() const {
|
||||||
|
return iterator(this, _root, nullid);
|
||||||
|
}
|
||||||
|
|
||||||
// Fields ==============================================================================================================
|
// Fields ==============================================================================================================
|
||||||
protected:
|
private:
|
||||||
table_t _table;
|
table_t _table;
|
||||||
freed_t _freed;
|
freed_t _freed;
|
||||||
size_t _root, _size;
|
size_t _root, _size;
|
||||||
|
|||||||
@@ -43,14 +43,24 @@ namespace fennec
|
|||||||
/// \tparam N The number of bits in the bitfield
|
/// \tparam N The number of bits in the bitfield
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct bitfield {
|
struct bitfield {
|
||||||
static constexpr size_t bits = N;
|
|
||||||
static constexpr size_t bytes = (N + 7) / 8;
|
|
||||||
|
|
||||||
|
// Constants ===========================================================================================================
|
||||||
public:
|
public:
|
||||||
|
static constexpr size_t bits = N; //!< The number of bits in the bitfield
|
||||||
|
static constexpr size_t bytes = (N + 7) / 8; //!< The number of bytes that hold the bitfield
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// \brief default constructor, initializes with \f$0\f$
|
||||||
constexpr bitfield()
|
constexpr bitfield()
|
||||||
: _bytes() {
|
: _bytes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief boolean array constructor
|
||||||
|
/// \param arr An array of boolean values resembling each bit.
|
||||||
explicit constexpr bitfield(const bool (&arr)[N])
|
explicit constexpr bitfield(const bool (&arr)[N])
|
||||||
: _bytes() {
|
: _bytes() {
|
||||||
for (size_t i = 0; i < arr; ++i) {
|
for (size_t i = 0; i < arr; ++i) {
|
||||||
@@ -58,6 +68,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief index array constructor
|
||||||
|
/// \param arr An array of indices values resembling which bits to set.
|
||||||
template<size_t I>
|
template<size_t I>
|
||||||
explicit constexpr bitfield(const size_t (&arr)[I])
|
explicit constexpr bitfield(const size_t (&arr)[I])
|
||||||
: _bytes() {
|
: _bytes() {
|
||||||
@@ -66,12 +79,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief variadic array constructor
|
||||||
|
/// \param args A set of indices values resembling which bits to set.
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr bitfield(ArgsT&&...args)
|
constexpr bitfield(ArgsT&&...args)
|
||||||
: _bytes() {
|
: _bytes() {
|
||||||
(this->store(fennec::forward<ArgsT>(args), true), ...);
|
(this->store(fennec::forward<ArgsT>(args), true), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param args A set of boolean values resembling each bit.
|
||||||
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
|
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
|
||||||
constexpr bitfield(ArgsT&&...args)
|
constexpr bitfield(ArgsT&&...args)
|
||||||
: _bytes() {
|
: _bytes() {
|
||||||
@@ -79,19 +97,40 @@ public:
|
|||||||
(this->store(i++, fennec::forward<ArgsT>(args)), ...);
|
(this->store(i++, fennec::forward<ArgsT>(args)), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief copy constructor
|
||||||
|
/// \param bf bitfield to copy
|
||||||
bitfield(const bitfield& bf)
|
bitfield(const bitfield& bf)
|
||||||
: _bytes(bf._bytes) {
|
: _bytes(bf._bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move constructor
|
||||||
|
/// \param bf bitfield to move
|
||||||
bitfield(bitfield&& bf) noexcept
|
bitfield(bitfield&& bf) noexcept
|
||||||
: _bytes(bf._bytes) {
|
: _bytes(bf._bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief destructor
|
||||||
constexpr ~bitfield() = default;
|
constexpr ~bitfield() = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief copy assignment
|
||||||
|
/// \param bf bitfield to copy
|
||||||
|
/// \returns a reference to self
|
||||||
bitfield& operator=(const bitfield& bf) = default;
|
bitfield& operator=(const bitfield& bf) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move assignment
|
||||||
|
/// \param bf bitfield to move
|
||||||
|
/// \returns a reference to self
|
||||||
bitfield& operator=(bitfield&& bf) noexcept = default;
|
bitfield& operator=(bitfield&& bf) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief test a bit
|
||||||
|
/// \param i the index of the bit
|
||||||
|
/// \returns the value stored in the bit as a boolean
|
||||||
bool test(size_t i) const {
|
bool test(size_t i) const {
|
||||||
assertd(i < bits, "Index out of Bounds!");
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
size_t b = i / 8;
|
size_t b = i / 8;
|
||||||
@@ -99,6 +138,9 @@ public:
|
|||||||
return _bytes[b] & (1 << o);
|
return _bytes[b] & (1 << o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief set a bit
|
||||||
|
/// \param i the index of the bit
|
||||||
void set(size_t i) {
|
void set(size_t i) {
|
||||||
assertd(i < bits, "Index out of Bounds!");
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
size_t b = i / 8;
|
size_t b = i / 8;
|
||||||
@@ -106,6 +148,9 @@ public:
|
|||||||
_bytes[b] |= (1 << o);
|
_bytes[b] |= (1 << o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief clear a bit
|
||||||
|
/// \param i the index of the bit
|
||||||
void clear(size_t i) {
|
void clear(size_t i) {
|
||||||
assertd(i < bits, "Index out of Bounds!");
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
size_t b = i / 8;
|
size_t b = i / 8;
|
||||||
@@ -113,6 +158,9 @@ public:
|
|||||||
_bytes[b] &= ~(1 << o);
|
_bytes[b] &= ~(1 << o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief toggle a bit
|
||||||
|
/// \param i the index of the bit
|
||||||
void toggle(size_t i) {
|
void toggle(size_t i) {
|
||||||
assertd(i < bits, "Index out of Bounds!");
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
size_t b = i / 8;
|
size_t b = i / 8;
|
||||||
@@ -120,6 +168,10 @@ public:
|
|||||||
_bytes[b] ^= (1 << o);
|
_bytes[b] ^= (1 << o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief store \f$v\f$ in bit \f$i\f$
|
||||||
|
/// \param i
|
||||||
|
/// \param v
|
||||||
void store(size_t i, bool v) {
|
void store(size_t i, bool v) {
|
||||||
assertd(i < bits, "Index out of Bounds!");
|
assertd(i < bits, "Index out of Bounds!");
|
||||||
size_t b = i / 8;
|
size_t b = i / 8;
|
||||||
@@ -127,6 +179,9 @@ public:
|
|||||||
(_bytes[b] &= ~((1 << o))) |= ((v << o));
|
(_bytes[b] &= ~((1 << o))) |= ((v << o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief not operator
|
||||||
|
/// \returns a bitfield containing the bit-wise inverse
|
||||||
bitfield operator~() const {
|
bitfield operator~() const {
|
||||||
bitfield res = *this;
|
bitfield res = *this;
|
||||||
res._inv_helper(make_index_metasequence_t<bytes>{});
|
res._inv_helper(make_index_metasequence_t<bytes>{});
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The underlying allocator type
|
||||||
using elem_t = node*;
|
using elem_t = node*; //!< The underlying element type
|
||||||
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
@@ -153,7 +153,7 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when the deque is empty, `false` otherwise
|
/// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocation, initializes a dynarray with `n` elements using the default constructor.
|
/// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor.
|
||||||
/// \param n The number of elements.
|
/// \param n The number of elements.
|
||||||
explicit constexpr dynarray(size_t n)
|
explicit constexpr dynarray(size_t n)
|
||||||
: _alloc(n)
|
: _alloc(n)
|
||||||
@@ -114,7 +114,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator `alloc` and `n` elements
|
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator \f$alloc\f$ and \f$n\f$ elements
|
||||||
/// using the default constructor.
|
/// using the default constructor.
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \param alloc The allocator object to copy
|
/// \param alloc The allocator object to copy
|
||||||
@@ -128,7 +128,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator `alloc` and `n` elements
|
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator \f$alloc\f$ and \f$n\f$ elements
|
||||||
/// using the default constructor.
|
/// using the default constructor.
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \param alloc The allocator object to copy
|
/// \param alloc The allocator object to copy
|
||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element
|
/// \brief Sized Allocation Copy Constructor, Create an allocation of size \f$n\f$ elements, with each element
|
||||||
/// constructed using the copy constructor
|
/// constructed using the copy constructor
|
||||||
/// \param n the number of elements
|
/// \param n the number of elements
|
||||||
/// \param val the value to copy
|
/// \param val the value to copy
|
||||||
@@ -267,7 +267,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Copy Assignment Operator
|
/// \brief Copy Assignment Operator
|
||||||
/// \param arr the array to copy
|
/// \param arr the array to copy
|
||||||
/// \returns A dynarray after having copied each element of `arr`
|
/// \returns A dynarray after having copied each element of \f$arr\f$
|
||||||
constexpr dynarray& operator=(const dynarray& arr) {
|
constexpr dynarray& operator=(const dynarray& arr) {
|
||||||
this->clear();
|
this->clear();
|
||||||
_alloc.creallocate(_size = arr._size);
|
_alloc.creallocate(_size = arr._size);
|
||||||
@@ -280,7 +280,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Move Assignment Operator
|
/// \brief Move Assignment Operator
|
||||||
/// \param arr the array to move
|
/// \param arr the array to move
|
||||||
/// \returns A dynarray after having taken ownership of the contents of `arr`
|
/// \returns A dynarray after having taken ownership of the contents of \f$arr\f$
|
||||||
constexpr dynarray& operator=(dynarray&& arr) noexcept {
|
constexpr dynarray& operator=(dynarray&& arr) noexcept {
|
||||||
this->clear();
|
this->clear();
|
||||||
_alloc = fennec::move(arr._alloc);
|
_alloc = fennec::move(arr._alloc);
|
||||||
@@ -293,7 +293,7 @@ public:
|
|||||||
/// \brief Array Copy Assignment Operator
|
/// \brief Array Copy Assignment Operator
|
||||||
/// \tparam N the length of the array
|
/// \tparam N the length of the array
|
||||||
/// \param arr the array to copy
|
/// \param arr the array to copy
|
||||||
/// \returns A dynarray after having copied each element of `arr`
|
/// \returns A dynarray after having copied each element of \f$arr\f$
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
constexpr dynarray& operator=(const TypeT (&arr)[N]) {
|
constexpr dynarray& operator=(const TypeT (&arr)[N]) {
|
||||||
this->clear();
|
this->clear();
|
||||||
@@ -308,7 +308,7 @@ public:
|
|||||||
/// \brief Array Copy Assignment Operator
|
/// \brief Array Copy Assignment Operator
|
||||||
/// \tparam N the length of the array
|
/// \tparam N the length of the array
|
||||||
/// \param arr the array to copy
|
/// \param arr the array to copy
|
||||||
/// \returns A dynarray after having moved each element of `arr`
|
/// \returns A dynarray after having moved each element of \f$arr\f$
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
constexpr dynarray& operator=(TypeT (&&arr)[N]) {
|
constexpr dynarray& operator=(TypeT (&&arr)[N]) {
|
||||||
this->clear();
|
this->clear();
|
||||||
@@ -355,7 +355,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i The index to access
|
/// \param i The index to access
|
||||||
/// \returns A reference to the element at index `i`
|
/// \returns A reference to the element at index \f$i\f$
|
||||||
constexpr TypeT& operator[](size_t i) {
|
constexpr TypeT& operator[](size_t i) {
|
||||||
assertd(i < _size, "Array Out of Bounds");
|
assertd(i < _size, "Array Out of Bounds");
|
||||||
return _alloc.data()[i];
|
return _alloc.data()[i];
|
||||||
@@ -364,7 +364,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator (const)
|
/// \brief Array Access Operator (const)
|
||||||
/// \param i The index to access
|
/// \param i The index to access
|
||||||
/// \returns A const qualified reference to the element at index `i`
|
/// \returns A const qualified reference to the element at index \f$i\f$
|
||||||
constexpr const TypeT& operator[](size_t i) const {
|
constexpr const TypeT& operator[](size_t i) const {
|
||||||
assertd(i < _size, "Array Out of Bounds");
|
assertd(i < _size, "Array Out of Bounds");
|
||||||
return _alloc.data()[i];
|
return _alloc.data()[i];
|
||||||
@@ -547,22 +547,21 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief "Iterator" Begin Function
|
|
||||||
/// \returns A pointer to the first element in the dynarray
|
/// \returns A pointer to the first element in the dynarray
|
||||||
constexpr TypeT* begin() { return _alloc.data(); }
|
constexpr TypeT* begin() { return _alloc.data(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief "Iterator" End Function
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns A const qualified pointer to the first element in the dynarray
|
||||||
|
constexpr const TypeT* begin() const { return _alloc; }
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
/// \return A pointer to the address after the last element in the dynarray
|
/// \return A pointer to the address after the last element in the dynarray
|
||||||
constexpr TypeT* end() { return begin() + _size; }
|
constexpr TypeT* end() { return begin() + _size; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Const "Iterator" Begin Function
|
/// \brief C++ Iterator Specification `end()`
|
||||||
/// \returns A const qualified pointer to the first element in the dynarray
|
|
||||||
constexpr const TypeT* begin() const { return _alloc; }
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Const "Iterator" End Function
|
|
||||||
/// \return A const qualified pointer to the address after the last element in the dynarray
|
/// \return A const qualified pointer to the address after the last element in the dynarray
|
||||||
constexpr const TypeT* end() const { return begin() + _size; }
|
constexpr const TypeT* end() const { return begin() + _size; }
|
||||||
|
|
||||||
|
|||||||
@@ -115,10 +115,15 @@ public:
|
|||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief runtime type acquisition
|
||||||
|
/// \returns a runtime type struct referencing the held type
|
||||||
type type() const {
|
type type() const {
|
||||||
return *static_cast<fennec::type*>(_manage(op_type, nullptr));
|
return *static_cast<fennec::type*>(_manage(op_type, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns \f$true\f$ if there is a held value, \f$false\f$ otherwise
|
||||||
bool has_value() const {
|
bool has_value() const {
|
||||||
return _handle != nullptr;
|
return _handle != nullptr;
|
||||||
}
|
}
|
||||||
@@ -126,6 +131,10 @@ public:
|
|||||||
|
|
||||||
// Assignment ==========================================================================================================
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief copy assignment
|
||||||
|
/// \param gen the generic to copy
|
||||||
|
/// \returns a reference to self after copying the contents of \f$gen\f$
|
||||||
generic& operator=(const generic& gen) {
|
generic& operator=(const generic& gen) {
|
||||||
if (this == &gen) { // self-assignment case
|
if (this == &gen) { // self-assignment case
|
||||||
return *this;
|
return *this;
|
||||||
@@ -137,14 +146,20 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move assignment
|
||||||
|
/// \param gen the generic to move
|
||||||
|
/// \returns a reference to self after swapping contents with \f$gen\f$
|
||||||
generic& operator=(generic&& gen) noexcept {
|
generic& operator=(generic&& gen) noexcept {
|
||||||
swap(gen);
|
swap(gen);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
// Utility =============================================================================================================
|
/// \brief value assignment
|
||||||
|
/// \tparam T the type of the value
|
||||||
|
/// \param x the value to assign
|
||||||
|
/// \returns a reference to self after having assigned \f$x\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
generic& operator=(T&& x) {
|
generic& operator=(T&& x) {
|
||||||
reset();
|
reset();
|
||||||
@@ -153,6 +168,16 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Utility =============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief emplace value
|
||||||
|
///
|
||||||
|
/// \details constructs a new value of type \f$T\f$ using \f$args...\f$
|
||||||
|
/// \tparam T the type to construct
|
||||||
|
/// \tparam ArgsT the argument types
|
||||||
|
/// \param args the argument values
|
||||||
template<typename T, typename...ArgsT>
|
template<typename T, typename...ArgsT>
|
||||||
void emplace(ArgsT&&...args) {
|
void emplace(ArgsT&&...args) {
|
||||||
reset();
|
reset();
|
||||||
@@ -160,6 +185,9 @@ public:
|
|||||||
_manage = _manage_impl<T>;
|
_manage = _manage_impl<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief reset value
|
||||||
|
/// \details clears the held value using the appropriate destructor
|
||||||
void reset() {
|
void reset() {
|
||||||
if (_manage) {
|
if (_manage) {
|
||||||
_handle = _manage(op_destroy, _handle);
|
_handle = _manage(op_destroy, _handle);
|
||||||
@@ -167,19 +195,32 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ 11 Swap Specification
|
||||||
|
/// \param gen the generic to swap with
|
||||||
void swap(generic& gen) noexcept {
|
void swap(generic& gen) noexcept {
|
||||||
fennec::swap(_handle, gen._handle);
|
fennec::swap(_handle, gen._handle);
|
||||||
fennec::swap(_manage, gen._manage);
|
fennec::swap(_manage, gen._manage);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
///
|
||||||
T& cast() {
|
/// \brief cast value
|
||||||
return *static_cast<T*>(_handle);
|
///
|
||||||
|
/// \details equivalent to `reinterpret_cast`
|
||||||
|
/// \tparam T The type to cast to
|
||||||
|
/// \returns The contents of generic after having cast to \f$T\f$
|
||||||
|
template<typename T, typename U = remove_cvref_t<T>>
|
||||||
|
T cast() {
|
||||||
|
return static_cast<T>(*static_cast<U*>(_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
///
|
||||||
const T& cast() const {
|
/// \details equivalent to `reinterpret_cast`
|
||||||
return *static_cast<T*>(_handle);
|
/// \tparam T The type to cast to
|
||||||
|
/// \returns The contents of generic after having cast to \f$T\f$
|
||||||
|
template<typename T, typename U = remove_cvref_t<T>>
|
||||||
|
T cast() const {
|
||||||
|
return static_cast<T>(*static_cast<U*>(_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -79,10 +79,10 @@ namespace fennec
|
|||||||
/// A directed graph is weakly connected if replacing all of its directed edges with undirected edges would
|
/// A directed graph is weakly connected if replacing all of its directed edges with undirected edges would
|
||||||
/// produce a connected graph. We will call this "disjointed"
|
/// produce a connected graph. We will call this "disjointed"
|
||||||
///
|
///
|
||||||
/// A directed graph is semi-connected if there is a directed path p for `u` → `v` *or* `v` → `u` for every
|
/// A directed graph is semi-connected if there is a directed path p for \f$u\f$ → \f$v\f$ *or* \f$v\f$ → \f$u\f$ for every
|
||||||
/// pair of vertices `u, v`. We will call this "unilateral"
|
/// pair of vertices `u, v`. We will call this "unilateral"
|
||||||
///
|
///
|
||||||
/// A directed graph is strongly-connected if there is a directed path p for `u` → `v` *and* `v` → `u` for every pair
|
/// A directed graph is strongly-connected if there is a directed path p for \f$u\f$ → \f$v\f$ *and* \f$v\f$ → \f$u\f$ for every pair
|
||||||
/// of vertices `u, v`. We will call this "connected"
|
/// of vertices `u, v`. We will call this "connected"
|
||||||
///
|
///
|
||||||
/// \tparam VertexT The type associated with each vertex
|
/// \tparam VertexT The type associated with each vertex
|
||||||
@@ -159,35 +159,35 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no vertices in the graph, `false` otherwise
|
/// \returns \f$true\f$ when there are no vertices in the graph, \f$false\f$ otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return num_vertices() == 0;
|
return num_vertices() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Checks if there exists an edge `e` that starts from `a` and ends at `b`
|
/// \brief Checks if there exists an edge \f$e\f$ that starts from \f$a\f$ and ends at \f$b\f$
|
||||||
/// \param a The first vertex
|
/// \param a The first vertex
|
||||||
/// \param b The second vertex
|
/// \param b The second vertex
|
||||||
/// \returns `true` if the edge exists, `false` otherwise
|
/// \returns \f$true\f$ if the edge exists, \f$false\f$ otherwise
|
||||||
constexpr bool exists(size_t a, size_t b) const {
|
constexpr bool exists(size_t a, size_t b) const {
|
||||||
return _edge_map[a][b] != nullptr;
|
return _edge_map[a][b] != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Checks if there exists an edge `e0` that starts from `a` and ends at `b` and `e1` that starts from `b`
|
/// \brief Checks if there exists an edge \f$e0\f$ that starts from \f$a\f$ and ends at \f$b\f$ and \f$e1\f$ that starts from \f$b\f$
|
||||||
/// and ends at `a`
|
/// and ends at \f$a\f$
|
||||||
/// \param a The first vertex
|
/// \param a The first vertex
|
||||||
/// \param b The second vertex
|
/// \param b The second vertex
|
||||||
/// \returns `true` if both edges exist, `false` otherwise
|
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
|
||||||
constexpr bool is_symmetric(size_t a, size_t b) const {
|
constexpr bool is_symmetric(size_t a, size_t b) const {
|
||||||
return exists(a, b) and exists(b, a);
|
return exists(a, b) and exists(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Checks if there exists an edge `e` between `a` and `b`
|
/// \brief Checks if there exists an edge \f$e\f$ between \f$a\f$ and \f$b\f$
|
||||||
/// \param a The first vertex
|
/// \param a The first vertex
|
||||||
/// \param b The second vertex
|
/// \param b The second vertex
|
||||||
/// \returns `true` if both edges exist, `false` otherwise
|
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
|
||||||
constexpr bool is_undirected(size_t a, size_t b) const {
|
constexpr bool is_undirected(size_t a, size_t b) const {
|
||||||
const auto* e0 = _edge_map[a][b];
|
const auto* e0 = _edge_map[a][b];
|
||||||
const auto* e1 = _edge_map[b][a];
|
const auto* e1 = _edge_map[b][a];
|
||||||
@@ -227,7 +227,7 @@ public:
|
|||||||
/// \brief edge Access Operator
|
/// \brief edge Access Operator
|
||||||
/// \param a The id of the first vertex
|
/// \param a The id of the first vertex
|
||||||
/// \param b The id of the second vertex
|
/// \param b The id of the second vertex
|
||||||
/// \returns A pointer to the value stored in the edge, `nullptr` if not found
|
/// \returns A pointer to the value stored in the edge, \f$nullptr\f$ if not found
|
||||||
constexpr edge_t* operator[](size_t a, size_t b) {
|
constexpr edge_t* operator[](size_t a, size_t b) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -243,7 +243,7 @@ public:
|
|||||||
/// \brief edge Const Access Operator
|
/// \brief edge Const Access Operator
|
||||||
/// \param a The id of the first vertex
|
/// \param a The id of the first vertex
|
||||||
/// \param b The id of the second vertex
|
/// \param b The id of the second vertex
|
||||||
/// \returns A const-qualified pointer to the value stored in the edge, `nullptr` if not found
|
/// \returns A const-qualified pointer to the value stored in the edge, \f$nullptr\f$ if not found
|
||||||
constexpr const edge_t* operator[](size_t a, size_t b) const {
|
constexpr const edge_t* operator[](size_t a, size_t b) const {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -256,9 +256,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to `x...`
|
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to `x...`
|
||||||
/// \param vertex The id of the vertex
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all vertices `x` with edges from `vertex` to `x...`
|
/// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to `x...`
|
||||||
list<size_t> outgoing(size_t vertex) {
|
list<size_t> outgoing(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || vertex >= _edge_map.size()) {
|
if (empty() || vertex >= _edge_map.size()) {
|
||||||
@@ -271,9 +271,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of vertices `x` that `vertex` has an edge from `x...`
|
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from `x...`
|
||||||
/// \param vertex The id of the vertex
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all vertices `x` with edges from `x...` to `vertex`
|
/// \returns A list containing all vertices \f$x\f$ with edges from `x...` to \f$vertex\f$
|
||||||
list<size_t> incoming(size_t vertex) {
|
list<size_t> incoming(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || vertex >= _edge_map.size()) {
|
if (empty() || vertex >= _edge_map.size()) {
|
||||||
@@ -288,9 +288,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to and from `x...`
|
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from `x...`
|
||||||
/// \param vertex The id of the vertex
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
|
||||||
list<size_t> symmetric(size_t vertex) {
|
list<size_t> symmetric(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || vertex >= _edge_map.size()) {
|
if (empty() || vertex >= _edge_map.size()) {
|
||||||
@@ -305,13 +305,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to and from `x...` and share the same value
|
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from `x...` and share the same value
|
||||||
/// \details
|
/// \details
|
||||||
/// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be
|
/// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be
|
||||||
/// turned into a directed edge by changing the weight object associated with the edge, or by
|
/// turned into a directed edge by changing the weight object associated with the edge, or by
|
||||||
/// removing one of the sub-edges.
|
/// removing one of the sub-edges.
|
||||||
/// \param vertex The id of the vertex
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
|
||||||
list<size_t> undirected(size_t vertex) {
|
list<size_t> undirected(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || vertex >= _edge_map.size()) {
|
if (empty() || vertex >= _edge_map.size()) {
|
||||||
@@ -381,7 +381,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Form an edge from vertex `a` to vertex `b`
|
/// \brief Form an edge from vertex \f$a\f$ to vertex \f$b\f$
|
||||||
/// \tparam ArgsT The argument types
|
/// \tparam ArgsT The argument types
|
||||||
/// \param a The first vertex id
|
/// \param a The first vertex id
|
||||||
/// \param b The second vertex id
|
/// \param b The second vertex id
|
||||||
@@ -408,7 +408,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Form an undirected edge between vertex `a` and vertex `b`
|
/// \brief Form an undirected edge between vertex \f$a\f$ and vertex \f$b\f$
|
||||||
/// \tparam ArgsT The argument types
|
/// \tparam ArgsT The argument types
|
||||||
/// \param a The first vertex id
|
/// \param a The first vertex id
|
||||||
/// \param b The second vertex id
|
/// \param b The second vertex id
|
||||||
@@ -437,7 +437,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Disconnect an edge from vertex `a` to vertex `b`
|
/// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$
|
||||||
/// \param a The first vertex id
|
/// \param a The first vertex id
|
||||||
/// \param b The second vertex id
|
/// \param b The second vertex id
|
||||||
constexpr void cut_edge(size_t a, size_t b) {
|
constexpr void cut_edge(size_t a, size_t b) {
|
||||||
@@ -460,7 +460,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Disconnect both directed edges between vertices `a` and `b`
|
/// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$
|
||||||
/// \param a The first vertex id
|
/// \param a The first vertex id
|
||||||
/// \param b The second vertex id
|
/// \param b The second vertex id
|
||||||
constexpr void cut_edge2(size_t a, size_t b) {
|
constexpr void cut_edge2(size_t a, size_t b) {
|
||||||
@@ -476,7 +476,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Break *all* edges to and from `n`
|
/// \brief Break *all* edges to and from \f$n\f$
|
||||||
/// \param n The vertex id
|
/// \param n The vertex id
|
||||||
void cut(size_t n) {
|
void cut(size_t n) {
|
||||||
for (const auto it : outgoing(n)) {
|
for (const auto it : outgoing(n)) {
|
||||||
|
|||||||
@@ -42,11 +42,17 @@ namespace fennec
|
|||||||
|
|
||||||
using std::initializer_list;
|
using std::initializer_list;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param inls the initializer list
|
||||||
|
/// \returns A const qualified pointer to the first element in \f$inls\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr const T* begin(initializer_list<T> inls) noexcept {
|
constexpr const T* begin(initializer_list<T> inls) noexcept {
|
||||||
return inls.begin();
|
return inls.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param inls the initializer list
|
||||||
|
/// \returns A const qualified pointer to one past the last element in \f$inls\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr const T* end(initializer_list<T> inls) noexcept {
|
constexpr const T* end(initializer_list<T> inls) noexcept {
|
||||||
return inls.end();
|
return inls.end();
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Constructor, copies all elements in `l` with optimized layout
|
/// \brief Copy Constructor, copies all elements in \f$l\f$ with optimized layout
|
||||||
/// \param l The list to copy
|
/// \param l The list to copy
|
||||||
constexpr list(const list& l)
|
constexpr list(const list& l)
|
||||||
: list() {
|
: list() {
|
||||||
@@ -134,7 +134,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Copy Assignment Operator
|
/// \brief Copy Assignment Operator
|
||||||
/// \param l the list to copy
|
/// \param l the list to copy
|
||||||
/// \returns `this` after having copied all elements of `l`
|
/// \returns \f$this\f$ after having copied all elements of \f$l\f$
|
||||||
constexpr list& operator=(const list& l) {
|
constexpr list& operator=(const list& l) {
|
||||||
this->clear();
|
this->clear();
|
||||||
for (const value_t& it : l) {
|
for (const value_t& it : l) {
|
||||||
@@ -146,7 +146,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Move Assignment Operator
|
/// \brief Move Assignment Operator
|
||||||
/// \param l the list to copy
|
/// \param l the list to copy
|
||||||
/// \returns `this` after having taken ownership over the contents of `l`
|
/// \returns \f$this\f$ after having taken ownership over the contents of \f$l\f$
|
||||||
constexpr list& operator=(list&& l) noexcept {
|
constexpr list& operator=(list&& l) noexcept {
|
||||||
this->clear();
|
this->clear();
|
||||||
_table = fennec::move(l._table);
|
_table = fennec::move(l._table);
|
||||||
@@ -177,7 +177,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when the list is empty, `false` otherwise.
|
/// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _root == npos;
|
return _root == npos;
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i Index to access
|
/// \param i Index to access
|
||||||
/// \returns A reference to the element at `i`
|
/// \returns A reference to the element at \f$i\f$
|
||||||
///
|
///
|
||||||
/// \details \f$O(N)\f$
|
/// \details \f$O(N)\f$
|
||||||
constexpr value_t& operator[](int i) {
|
constexpr value_t& operator[](int i) {
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Const Array Access Operator
|
/// \brief Const Array Access Operator
|
||||||
/// \param i Index to access
|
/// \param i Index to access
|
||||||
/// \returns A const-qualified reference to the element at `i`
|
/// \returns A const-qualified reference to the element at \f$i\f$
|
||||||
///
|
///
|
||||||
/// \details \f$O(N)\f$
|
/// \details \f$O(N)\f$
|
||||||
constexpr const value_t& operator[](int i) const {
|
constexpr const value_t& operator[](int i) const {
|
||||||
@@ -417,7 +417,6 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief C++ Iterator Specification `begin()`
|
|
||||||
/// \returns An iterator for the first element in the list
|
/// \returns An iterator for the first element in the list
|
||||||
constexpr iterator begin() {
|
constexpr iterator begin() {
|
||||||
return iterator(this, _root);
|
return iterator(this, _root);
|
||||||
@@ -431,7 +430,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Const C++ Iterator Specification `begin()`
|
|
||||||
/// \returns A const iterator for the first element in the list
|
/// \returns A const iterator for the first element in the list
|
||||||
constexpr const_iterator begin() const {
|
constexpr const_iterator begin() const {
|
||||||
return const_iterator(this, _root);
|
return const_iterator(this, _root);
|
||||||
@@ -447,37 +445,60 @@ public:
|
|||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Iterator Class
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
class iterator {
|
class iterator {
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief destructor
|
||||||
~iterator() {
|
~iterator() {
|
||||||
_list = nullptr;
|
_list = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix operator
|
///
|
||||||
|
/// \brief prefix increment operator
|
||||||
|
/// \param rhs the iterator to increment
|
||||||
|
/// \returns \f$rhs\f$ after having moved to the next element in the list
|
||||||
constexpr friend iterator& operator++(iterator& rhs) {
|
constexpr friend iterator& operator++(iterator& rhs) {
|
||||||
rhs._n = rhs._list->_next(rhs._n);
|
rhs._n = rhs._list->_next(rhs._n);
|
||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \param lhs the iterator to increment
|
||||||
|
/// \returns \f$lhs\f$ before having moved to the next element in the list
|
||||||
constexpr friend iterator operator++(iterator& lhs, int) {
|
constexpr friend iterator operator++(iterator& lhs, int) {
|
||||||
iterator prev = lhs;
|
iterator prev = lhs;
|
||||||
++lhs;
|
++lhs;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
constexpr value_t& operator*() {
|
constexpr value_t& operator*() {
|
||||||
return *(_list->_table[_n].value);
|
return *(_list->_table[_n].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
constexpr value_t* operator->() {
|
constexpr value_t* operator->() {
|
||||||
return &*(_list->_table[_n].value);
|
return &*(_list->_table[_n].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
constexpr bool operator==(const iterator& it) {
|
constexpr bool operator==(const iterator& it) {
|
||||||
return _list == it._list and _n == it._n;
|
return _list == it._list and _n == it._n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
constexpr bool operator!=(const iterator& it) {
|
constexpr bool operator!=(const iterator& it) {
|
||||||
return _list != it._list or _n != it._n;
|
return _list != it._list or _n != it._n;
|
||||||
}
|
}
|
||||||
@@ -497,11 +518,16 @@ public:
|
|||||||
/// \brief Iterator Class for Const Access
|
/// \brief Iterator Class for Const Access
|
||||||
class const_iterator {
|
class const_iterator {
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief destructor
|
||||||
~const_iterator() {
|
~const_iterator() {
|
||||||
_list = nullptr;
|
_list = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix operator
|
///
|
||||||
|
/// \brief prefix increment operator
|
||||||
|
/// \param rhs the iterator to increment
|
||||||
|
/// \returns \f$rhs\f$ after having moved to the next element in the list
|
||||||
constexpr friend const_iterator& operator++(const_iterator& rhs) {
|
constexpr friend const_iterator& operator++(const_iterator& rhs) {
|
||||||
if (rhs._list->_next(rhs._n) < rhs._list->capacity()) {
|
if (rhs._list->_next(rhs._n) < rhs._list->capacity()) {
|
||||||
return rhs;
|
return rhs;
|
||||||
@@ -510,24 +536,42 @@ public:
|
|||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \param lhs the iterator to increment
|
||||||
|
/// \returns \f$lhs\f$ before having moved to the next element in the list
|
||||||
constexpr friend const_iterator operator++(const_iterator& lhs, int) {
|
constexpr friend const_iterator operator++(const_iterator& lhs, int) {
|
||||||
const_iterator prev = lhs;
|
const_iterator prev = lhs;
|
||||||
++lhs;
|
++lhs;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
constexpr const value_t& operator*() {
|
constexpr const value_t& operator*() {
|
||||||
return *(_list->_table[_n].value);
|
return *(_list->_table[_n].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
constexpr const value_t* operator->() {
|
constexpr const value_t* operator->() {
|
||||||
return &*(_list->_table[_n].value);
|
return &*(_list->_table[_n].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
constexpr bool operator==(const const_iterator& it) {
|
constexpr bool operator==(const const_iterator& it) {
|
||||||
return _list == it._list and _n == it._n;
|
return _list == it._list and _n == it._n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
constexpr bool operator!=(const const_iterator& it) {
|
constexpr bool operator!=(const const_iterator& it) {
|
||||||
return _list != it._list or _n != it._n;
|
return _list != it._list or _n != it._n;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace fennec
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Data Structure defining a mapping of `key` \f$KeyT\f$ to `value` \f$ValueT\f$
|
/// \brief Data Structure defining a mapping of \f$key\f$ \f$KeyT\f$ to \f$value\f$ \f$ValueT\f$
|
||||||
/// \details
|
/// \details
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
/// |:----------:|:----------:|
|
/// |:----------:|:----------:|
|
||||||
@@ -91,15 +91,26 @@ public:
|
|||||||
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; ///< The underlying set
|
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; ///< The underlying set
|
||||||
using iterator = set_t::iterator; ///< Iterator type
|
using iterator = set_t::iterator; ///< Iterator type
|
||||||
|
|
||||||
// We only want to hash the key
|
///
|
||||||
|
/// \brief key hash helper
|
||||||
struct key_hash : hash_t {
|
struct key_hash : hash_t {
|
||||||
|
///
|
||||||
|
/// \brief C++ 11 Hash Specification `operator()`
|
||||||
|
/// \param p the pair to hash
|
||||||
|
/// \returns the hash of the key
|
||||||
constexpr size_t operator()(const elem_t& p) const {
|
constexpr size_t operator()(const elem_t& p) const {
|
||||||
return hash_t::operator()(p.first);
|
return hash_t::operator()(p.first);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// We only want to compare the keys
|
///
|
||||||
|
/// \brief key comparison helper
|
||||||
struct key_equals : equality<KeyT> {
|
struct key_equals : equality<KeyT> {
|
||||||
|
///
|
||||||
|
/// \brief C++ 11 Compare Specification `operator()`
|
||||||
|
/// \param a the first pair
|
||||||
|
/// \param b the second pair
|
||||||
|
/// \returns \f$true\f$ if the keys are equal, \f$false\f$ otherwise
|
||||||
constexpr bool operator()(const elem_t& a, const elem_t& b) const {
|
constexpr bool operator()(const elem_t& a, const elem_t& b) const {
|
||||||
return equality<KeyT>::operator()(a.first, b.first);
|
return equality<KeyT>::operator()(a.first, b.first);
|
||||||
}
|
}
|
||||||
@@ -134,7 +145,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no elements in the set, `false` otherwise
|
/// \returns \f$true\f$ when there are no elements in the set, \f$false\f$ otherwise
|
||||||
constexpr size_t empty() const {
|
constexpr size_t empty() const {
|
||||||
return _set.size();
|
return _set.size();
|
||||||
}
|
}
|
||||||
@@ -156,7 +167,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Key Access Operator
|
/// \brief Key Access Operator
|
||||||
/// \param key Key value to access
|
/// \param key Key value to access
|
||||||
/// \returns A pointer to the value associated with `key`, `nullptr` if `key` is not present.
|
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
|
||||||
constexpr value_t* operator[](const KeyT& key) {
|
constexpr value_t* operator[](const KeyT& key) {
|
||||||
auto it = _set.at(this->_find(key));
|
auto it = _set.at(this->_find(key));
|
||||||
return it ? &it->second : nullptr;
|
return it ? &it->second : nullptr;
|
||||||
@@ -165,7 +176,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Key Const Access Operator
|
/// \brief Key Const Access Operator
|
||||||
/// \param key Key value to access
|
/// \param key Key value to access
|
||||||
/// \returns A const-qualified pointer to the value associated with `key`, `nullptr` if `key` is not present.
|
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
|
||||||
constexpr const value_t* operator[](const KeyT& key) const {
|
constexpr const value_t* operator[](const KeyT& key) const {
|
||||||
auto it = _set.at(this->_find(key));
|
auto it = _set.at(this->_find(key));
|
||||||
return it ? &it->second : nullptr;
|
return it ? &it->second : nullptr;
|
||||||
@@ -175,7 +186,7 @@ public:
|
|||||||
/// \brief Argument Key Access Operator
|
/// \brief Argument Key Access Operator
|
||||||
/// \tparam ArgsT Argument Types
|
/// \tparam ArgsT Argument Types
|
||||||
/// \param args Arguments to construct the key with
|
/// \param args Arguments to construct the key with
|
||||||
/// \returns A pointer to the value associated with `key`, `nullptr` if `key` is not present.
|
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr value_t* operator[](ArgsT&&...args) {
|
constexpr value_t* operator[](ArgsT&&...args) {
|
||||||
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
|
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
|
||||||
@@ -186,7 +197,7 @@ public:
|
|||||||
/// \brief Argument Key Const Access Operator
|
/// \brief Argument Key Const Access Operator
|
||||||
/// \tparam ArgsT Argument Type
|
/// \tparam ArgsT Argument Type
|
||||||
/// \param args Argument to construct the key with
|
/// \param args Argument to construct the key with
|
||||||
/// \returns A const-qualified pointer to the value associated with `key`, `nullptr` if `key` is not present.
|
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr const value_t* operator[](ArgsT&&...args) const {
|
constexpr const value_t* operator[](ArgsT&&...args) const {
|
||||||
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
|
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ struct object_pool {
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT; //!< The held object type
|
||||||
using elem_t = optional<value_t>;
|
using elem_t = optional<value_t>; //!< The element type
|
||||||
using table_t = dynarray<elem_t, AllocT>;
|
using table_t = dynarray<elem_t, AllocT>; //!< The underlying table type
|
||||||
using freed_t = list<size_t, AllocT>;
|
using freed_t = list<size_t, AllocT>; //!< The underlying free queue
|
||||||
|
|
||||||
class iterator;
|
class iterator;
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
@@ -92,13 +92,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no objects in the pool, `false` otherwise
|
/// \returns \f$true\f$ when there are no objects in the pool, \f$false\f$ otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Retrieve the next id `i` that would be assigned to an object `o` were it added to the object pool
|
/// \brief Retrieve the next id \f$i\f$ that would be assigned to an object \f$o\f$ were it added to the object pool
|
||||||
///
|
///
|
||||||
/// \details This can be useful if there are constant members that need to be assigned at construction.
|
/// \details This can be useful if there are constant members that need to be assigned at construction.
|
||||||
/// \returns The id of the next inserted node
|
/// \returns The id of the next inserted node
|
||||||
@@ -120,7 +120,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i id of the object
|
/// \param i id of the object
|
||||||
/// \returns a reference to the object with id `i`
|
/// \returns a reference to the object with id \f$i\f$
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access null object.")
|
assert(_table[i], "Attempted to access null object.")
|
||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Const Access Operator
|
/// \brief Array Const Access Operator
|
||||||
/// \param i id of the object
|
/// \param i id of the object
|
||||||
/// \returns a const-qualified reference to the object with id `i`
|
/// \returns a const-qualified reference to the object with id \f$i\f$
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access null object.")
|
assert(_table[i], "Attempted to access null object.")
|
||||||
@@ -146,7 +146,7 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Insertion, inserts `x` into the pool
|
/// \brief Move Insertion, inserts \f$x\f$ into the pool
|
||||||
/// \param x the object to move
|
/// \param x the object to move
|
||||||
/// \returns An integer corresponding to the id of the node
|
/// \returns An integer corresponding to the id of the node
|
||||||
constexpr size_t insert(value_t&& x) {
|
constexpr size_t insert(value_t&& x) {
|
||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Insertion, inserts a copy of `x` into the pool
|
/// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool
|
||||||
/// \param x the object to copy
|
/// \param x the object to copy
|
||||||
/// \returns An integer corresponding to the id of the node
|
/// \returns An integer corresponding to the id of the node
|
||||||
constexpr size_t insert(const value_t& x) {
|
constexpr size_t insert(const value_t& x) {
|
||||||
@@ -195,62 +195,108 @@ public:
|
|||||||
|
|
||||||
// Iterator ============================================================================================================
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns an iterator at the start of the object pool
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
return iterator(this, 0);
|
return iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end() {
|
///
|
||||||
return iterator(this, _size);
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
}
|
/// \returns an iterator at the start of the object pool
|
||||||
|
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
return iterator(this, 0);
|
return iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns an iterator at the start of the end of the object pool
|
||||||
|
iterator end() {
|
||||||
|
return iterator(this, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
|
/// \returns an iterator at the start of the end of the object pool
|
||||||
const_iterator end() const {
|
const_iterator end() const {
|
||||||
return iterator(this, _size);
|
return iterator(this, _size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
class iterator {
|
class iterator {
|
||||||
public:
|
public:
|
||||||
iterator(object_pool* pool, size_t start)
|
///
|
||||||
: pool(pool), curr(start) {
|
/// \brief copy constructor
|
||||||
_fix();
|
/// \param it the iterator to copy
|
||||||
}
|
iterator(const iterator& it) = default;
|
||||||
|
|
||||||
iterator(const iterator&) = default;
|
///
|
||||||
iterator(iterator&&) noexcept = default;
|
/// \brief move constructor
|
||||||
|
/// \param it the iterator to move
|
||||||
|
iterator(iterator&& it) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief public destructor
|
||||||
~iterator() = default;
|
~iterator() = default;
|
||||||
|
|
||||||
iterator& operator=(const iterator&) = default;
|
|
||||||
iterator& operator=(iterator&&) noexcept = default;
|
|
||||||
|
|
||||||
iterator operator++(int) {
|
///
|
||||||
iterator ret = *this;
|
/// \brief copy assignment
|
||||||
++curr;
|
/// \param it the iterator to copy
|
||||||
_fix();
|
/// \returns a reference to self after having copied \f$it\f$
|
||||||
|
iterator& operator=(const iterator& it) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move assignment
|
||||||
|
/// \param it the iterator to move
|
||||||
|
/// \returns a reference to self after having moved \f$it\f$
|
||||||
|
iterator& operator=(iterator&& it) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \returns \f$it\f$ before having been incremented
|
||||||
|
friend iterator operator++(iterator& it, int) {
|
||||||
|
iterator ret = it;
|
||||||
|
++it.curr;
|
||||||
|
it._fix();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator& operator++() {
|
///
|
||||||
++curr;
|
/// \brief prefix increment operator
|
||||||
_fix();
|
/// \returns \f$it\f$ after having moved to the next element
|
||||||
return *this;
|
friend iterator& operator++(iterator& it) {
|
||||||
|
++it.curr;
|
||||||
|
it._fix();
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
value_t& operator*() const {
|
value_t& operator*() const {
|
||||||
return *pool->_table[curr];
|
return *pool->_table[curr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
value_t* operator->() const {
|
value_t* operator->() const {
|
||||||
return *pool->_table[curr];
|
return *pool->_table[curr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
bool operator==(const iterator& it) {
|
bool operator==(const iterator& it) {
|
||||||
return pool == it.pool and curr == it.curr;
|
return pool == it.pool and curr == it.curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
bool operator!=(const iterator& it) {
|
bool operator!=(const iterator& it) {
|
||||||
return pool != it.pool or curr != it.curr;
|
return pool != it.pool or curr != it.curr;
|
||||||
}
|
}
|
||||||
@@ -264,48 +310,91 @@ public:
|
|||||||
++curr;
|
++curr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class const_iterator {
|
iterator(object_pool* pool, size_t start)
|
||||||
public:
|
|
||||||
const_iterator(const object_pool* pool, size_t start)
|
|
||||||
: pool(pool), curr(start) {
|
: pool(pool), curr(start) {
|
||||||
_fix();
|
_fix();
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator(const const_iterator&) = default;
|
friend struct object_pool;
|
||||||
const_iterator(const_iterator&&) noexcept = default;
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `const_iterator`
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// \brief copy constructor
|
||||||
|
/// \param it the iterator to copy
|
||||||
|
const_iterator(const const_iterator&it ) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move constructor
|
||||||
|
/// \param it the iterator to move
|
||||||
|
const_iterator(const_iterator&& it) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief public destructor
|
||||||
~const_iterator() = default;
|
~const_iterator() = default;
|
||||||
|
|
||||||
const_iterator& operator=(const const_iterator&) = default;
|
|
||||||
const_iterator& operator=(const_iterator&&) noexcept = default;
|
|
||||||
|
|
||||||
const_iterator operator++(int) {
|
///
|
||||||
const_iterator ret = *this;
|
/// \brief copy assignment
|
||||||
++curr;
|
/// \param it the iterator to copy
|
||||||
_fix();
|
/// \returns a reference to self after having copied \f$it\f$
|
||||||
|
const_iterator& operator=(const const_iterator& it) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move assignment
|
||||||
|
/// \param it the iterator to move
|
||||||
|
/// \returns a reference to self after having moved \f$it\f$
|
||||||
|
const_iterator& operator=(const_iterator&& it) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \returns \f$it\f$ before having been incremented
|
||||||
|
friend const_iterator operator++(const_iterator& it, int) {
|
||||||
|
const_iterator ret = it;
|
||||||
|
++it.curr;
|
||||||
|
it._fix();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator& operator++() {
|
///
|
||||||
++curr;
|
/// \brief prefix increment operator
|
||||||
_fix();
|
/// \returns \f$it\f$ after having moved to the next element
|
||||||
return *this;
|
friend const_iterator& operator++(const_iterator& it) {
|
||||||
|
++it.curr;
|
||||||
|
it._fix();
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
const value_t& operator*() const {
|
const value_t& operator*() const {
|
||||||
return *pool->_table[curr];
|
return *pool->_table[curr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
const value_t* operator->() const {
|
const value_t* operator->() const {
|
||||||
return *pool->_table[curr];
|
return *pool->_table[curr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
bool operator==(const const_iterator& it) {
|
bool operator==(const const_iterator& it) {
|
||||||
return pool == it.pool and curr == it.curr;
|
return pool == it.pool and curr == it.curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
bool operator!=(const const_iterator& it) {
|
bool operator!=(const const_iterator& it) {
|
||||||
return pool != it.pool or curr != it.curr;
|
return pool != it.pool or curr != it.curr;
|
||||||
}
|
}
|
||||||
@@ -319,6 +408,13 @@ public:
|
|||||||
++curr;
|
++curr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const_iterator(const object_pool* pool, size_t start)
|
||||||
|
: pool(pool), curr(start) {
|
||||||
|
_fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend struct object_pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -38,10 +38,16 @@
|
|||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
///
|
||||||
|
/// \brief struct to represent a \f$null\f$ `optional`
|
||||||
struct nullopt_t {};
|
struct nullopt_t {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief value representing a \f$null\f$ `optional`
|
||||||
constexpr nullopt_t nullopt_v = {};
|
constexpr nullopt_t nullopt_v = {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief alias for representing a \f$null\f$ `optional`
|
||||||
#define nullopt nullopt_v
|
#define nullopt nullopt_v
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -52,10 +58,10 @@ struct optional {
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using reference_t = T&;
|
using reference_t = T&; //!< reference type
|
||||||
using pointer_t = T*;
|
using pointer_t = T*; //!< pointer type
|
||||||
using const_reference_t = T&;
|
using const_reference_t = T&; //!< const reference type
|
||||||
using const_pointer_t = const T*;
|
using const_pointer_t = const T*; //!< const pointer type
|
||||||
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
@@ -116,12 +122,18 @@ public:
|
|||||||
opt = nullopt;
|
opt = nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Constructor
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The argument values
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr optional(ArgsT&&...args)
|
constexpr optional(ArgsT&&...args)
|
||||||
: _val(fennec::forward<ArgsT>(args)...)
|
: _val(fennec::forward<ArgsT>(args)...)
|
||||||
, _set(true) {
|
, _set(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief destructor
|
||||||
constexpr ~optional() {
|
constexpr ~optional() {
|
||||||
if constexpr(is_fundamental_v<T>) {
|
if constexpr(is_fundamental_v<T>) {
|
||||||
return;
|
return;
|
||||||
@@ -141,13 +153,13 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Implicit Boolean Check
|
/// \brief Implicit Boolean Check
|
||||||
/// \returns `true` when there is a value contained
|
/// \returns \f$true\f$ when there is a value contained
|
||||||
constexpr operator bool() const {
|
constexpr operator bool() const {
|
||||||
return _set;
|
return _set;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there is no held value, `false` otherwise.
|
/// \returns \f$true\f$ when there is no held value, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return not _set;
|
return not _set;
|
||||||
}
|
}
|
||||||
@@ -249,13 +261,13 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns A pointer to the value, `nullptr` if there is no value
|
/// \returns A pointer to the value, \f$nullptr\f$ if there is no value
|
||||||
constexpr pointer_t operator->() noexcept {
|
constexpr pointer_t operator->() noexcept {
|
||||||
return _set ? &_val : nullptr;
|
return _set ? &_val : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns A const-qualified pointer to the value, `nullptr` if there is no value
|
/// \returns A const-qualified pointer to the value, \f$nullptr\f$ if there is no value
|
||||||
constexpr const_pointer_t operator->() const noexcept {
|
constexpr const_pointer_t operator->() const noexcept {
|
||||||
return _set ? &_val : nullptr;
|
return _set ? &_val : nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Equality Operator
|
/// \brief Equality Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns `true` when both elements of each pair are equal
|
/// \returns \f$true\f$ when both elements of each pair are equal
|
||||||
constexpr bool operator==(const pair& p) const {
|
constexpr bool operator==(const pair& p) const {
|
||||||
return first == p.first and second == p.second;
|
return first == p.first and second == p.second;
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Inequality Operator
|
/// \brief Inequality Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns `true` when either element of each pair are equal
|
/// \returns \f$true\f$ when either element of each pair are equal
|
||||||
constexpr bool operator!=(const pair& p) const {
|
constexpr bool operator!=(const pair& p) const {
|
||||||
return first != p.first or second != p.second;
|
return first != p.first or second != p.second;
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Less Than Operator
|
/// \brief Less Than Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns lexical comparison of both elements, i.e. returns `true` when the first element is less, or they are
|
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
|
||||||
/// equal and the second element is less
|
/// equal and the second element is less
|
||||||
constexpr bool operator<(const pair& p) const {
|
constexpr bool operator<(const pair& p) const {
|
||||||
return first < p.first or (first == p.first and second < p.second);
|
return first < p.first or (first == p.first and second < p.second);
|
||||||
@@ -165,7 +165,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Less Equal Operator
|
/// \brief Less Equal Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns lexical comparison of both elements, i.e. returns `true` when the first element is less, or they are
|
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
|
||||||
/// equal and the second element is less or equal
|
/// equal and the second element is less or equal
|
||||||
constexpr bool operator<=(const pair& p) const {
|
constexpr bool operator<=(const pair& p) const {
|
||||||
return first < p.first or (first == p.first and second <= p.second);
|
return first < p.first or (first == p.first and second <= p.second);
|
||||||
@@ -174,7 +174,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Greater Than Operator
|
/// \brief Greater Than Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns lexical comparison of both elements, i.e. returns `true` when the first element is greater, or they are
|
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
|
||||||
/// equal and the second element is greater
|
/// equal and the second element is greater
|
||||||
constexpr bool operator>(const pair& p) const {
|
constexpr bool operator>(const pair& p) const {
|
||||||
return first > p.first or (first == p.first and second > p.second);
|
return first > p.first or (first == p.first and second > p.second);
|
||||||
@@ -183,7 +183,7 @@ struct pair {
|
|||||||
///
|
///
|
||||||
/// \brief Greater Equal Operator
|
/// \brief Greater Equal Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
/// \returns lexical comparison of both elements, i.e. returns `true` when the first element is greater, or they are
|
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
|
||||||
/// equal and the second element is greater or equal
|
/// equal and the second element is greater or equal
|
||||||
constexpr bool operator>=(const pair& p) const {
|
constexpr bool operator>=(const pair& p) const {
|
||||||
return first > p.first or (first == p.first and second >= p.second);
|
return first > p.first or (first == p.first and second >= p.second);
|
||||||
@@ -192,8 +192,16 @@ struct pair {
|
|||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ 11 Hash Specification for `pair<TypeT0, TypeT1>`
|
||||||
|
/// \tparam TypeT0 The first type of the pair
|
||||||
|
/// \tparam TypeT1 The second type of the pair
|
||||||
template<typename TypeT0, typename TypeT1>
|
template<typename TypeT0, typename TypeT1>
|
||||||
struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> {
|
struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> {
|
||||||
|
///
|
||||||
|
/// \brief C++ 11 Hash Specification `operator()`
|
||||||
|
/// \param p The pair to hash
|
||||||
|
/// \returns a pairing of the hashes of both elements of \f$p\f$ using `fennec::pair_hash`
|
||||||
constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const {
|
constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const {
|
||||||
return fennec::pair_hash( // pair the hashes of both elements
|
return fennec::pair_hash( // pair the hashes of both elements
|
||||||
hash<TypeT0>::operator()(p.first),
|
hash<TypeT0>::operator()(p.first),
|
||||||
|
|||||||
@@ -53,16 +53,21 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief a priority queue data structure implemented using a binary heap
|
||||||
|
/// \tparam ValueT The value type
|
||||||
|
/// \tparam CompareT The compare type, defaults to `fennec::less`
|
||||||
|
/// \tparam AllocT The allocator type, defaults to `fennec::allocator`
|
||||||
template<typename ValueT, class CompareT = less<ValueT>, class AllocT = allocator<ValueT>>
|
template<typename ValueT, class CompareT = less<ValueT>, class AllocT = allocator<ValueT>>
|
||||||
struct priority_queue {
|
struct priority_queue {
|
||||||
|
|
||||||
// Definitions & Constants =============================================================================================
|
// Definitions & Constants =============================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = ValueT;
|
using value_t = ValueT; //!< Alias for the value type
|
||||||
using compare_t = CompareT;
|
using compare_t = CompareT; //!< Alias for the compare type
|
||||||
using alloc_t = allocation<value_t, AllocT>;
|
using alloc_t = allocation<value_t, AllocT>; //!< The underlying allocation type
|
||||||
|
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1; //!< value representing a null node
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr size_t left(size_t n) const {
|
constexpr size_t left(size_t n) const {
|
||||||
@@ -82,10 +87,15 @@ private:
|
|||||||
|
|
||||||
// Constructors & Destructor ===========================================================================================
|
// Constructors & Destructor ===========================================================================================
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief default constructor
|
||||||
|
/// \details initializes an empty queue
|
||||||
constexpr priority_queue()
|
constexpr priority_queue()
|
||||||
: _size(0) {
|
: _size(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief destructor
|
||||||
constexpr ~priority_queue() {
|
constexpr ~priority_queue() {
|
||||||
while (_size > 0) {
|
while (_size > 0) {
|
||||||
--_size;
|
--_size;
|
||||||
@@ -96,14 +106,20 @@ public:
|
|||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the size of the queue
|
||||||
constexpr size_t size() const {
|
constexpr size_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the capacity of the underlying allocation
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
return _table.capacity();
|
return _table.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns \f$true\f$ if the queue holds no elements
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
@@ -111,6 +127,8 @@ public:
|
|||||||
|
|
||||||
// Access ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the value at the front of the queue
|
||||||
constexpr const value_t& front() const {
|
constexpr const value_t& front() const {
|
||||||
return _table[0];
|
return _table[0];
|
||||||
}
|
}
|
||||||
@@ -118,19 +136,30 @@ public:
|
|||||||
|
|
||||||
// Modifiers ===========================================================================================================
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief push a new key into the queue
|
||||||
|
/// \param key the key to insert
|
||||||
constexpr void push(const value_t& key) {
|
constexpr void push(const value_t& key) {
|
||||||
this->_insert(key);
|
this->_insert(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param key the key to insert
|
||||||
constexpr void push(value_t&& key) {
|
constexpr void push(value_t&& key) {
|
||||||
this->_insert(fennec::forward<value_t>(key));
|
this->_insert(fennec::forward<value_t>(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief emplace a new key into the queue
|
||||||
|
/// \tparam ArgsT the argument types
|
||||||
|
/// \param args the argument values
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr void emplace(ArgsT&&...args) {
|
constexpr void emplace(ArgsT&&...args) {
|
||||||
this->_insert(fennec::forward<ArgsT>(args)...);
|
this->_insert(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pop the element at the front of the queue
|
||||||
constexpr void pop() {
|
constexpr void pop() {
|
||||||
fennec::swap(_table[0], _table[--_size]);
|
fennec::swap(_table[0], _table[--_size]);
|
||||||
fennec::destruct(&_table[_size]);
|
fennec::destruct(&_table[_size]);
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ template<typename TypeT, typename AllocT = allocator<TypeT>>
|
|||||||
struct rdtree {
|
struct rdtree {
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
protected:
|
private:
|
||||||
struct node;
|
struct node;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT; //!< the held value type
|
||||||
using alloc_t = typename allocator_traits<AllocT>::template rebind<node>;
|
using alloc_t = typename allocator_traits<AllocT>::template rebind<node>; //!< the underlying allocator type
|
||||||
static constexpr size_t root = 0;
|
static constexpr size_t root = 0; //!< the id of the root node
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1; //!< the id of a null node
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
struct node {
|
struct node {
|
||||||
value_t value;
|
value_t value;
|
||||||
size_t parent, child, prev, next;
|
size_t parent, child, prev, next;
|
||||||
@@ -107,14 +107,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Constructor, copies the contents of `tree`
|
/// \brief Copy Constructor, copies the contents of \f$tree\f$
|
||||||
/// \param tree the rdtree to copy
|
/// \param tree the rdtree to copy
|
||||||
constexpr rdtree(const rdtree& tree)
|
constexpr rdtree(const rdtree& tree)
|
||||||
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
|
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor, takes ownership over the contents of `tree`
|
/// \brief Move Constructor, takes ownership over the contents of \f$tree\f$
|
||||||
/// \param tree the rdtree to move
|
/// \param tree the rdtree to move
|
||||||
constexpr rdtree(rdtree&& tree) noexcept
|
constexpr rdtree(rdtree&& tree) noexcept
|
||||||
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
|
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
|
||||||
@@ -131,7 +131,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Copy Assignment Operator
|
/// \brief Copy Assignment Operator
|
||||||
/// \param rhs the rdtree to copy
|
/// \param rhs the rdtree to copy
|
||||||
/// \returns `this` after copying the contents of `rhs`
|
/// \returns \f$this\f$ after copying the contents of \f$rhs\f$
|
||||||
constexpr rdtree& operator=(const rdtree& rhs) {
|
constexpr rdtree& operator=(const rdtree& rhs) {
|
||||||
for (value_t* it : this->_table) {
|
for (value_t* it : this->_table) {
|
||||||
fennec::destruct(it);
|
fennec::destruct(it);
|
||||||
@@ -145,7 +145,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Move Assignment Operator
|
/// \brief Move Assignment Operator
|
||||||
/// \param rhs the rdtree to move
|
/// \param rhs the rdtree to move
|
||||||
/// \returns `this` after taking ownership over the contents of `rhs`
|
/// \returns \f$this\f$ after taking ownership over the contents of \f$rhs\f$
|
||||||
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
|
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
|
||||||
for (value_t* it : _table) {
|
for (value_t* it : _table) {
|
||||||
fennec::destruct(it);
|
fennec::destruct(it);
|
||||||
@@ -176,7 +176,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no nodes in the tree, `false` otherwise
|
/// \returns \f$true\f$ when there are no nodes in the tree, \f$false\f$ otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
@@ -256,7 +256,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param i the node to start at
|
/// \param i the node to start at
|
||||||
/// \returns the left-most child of node `i`
|
/// \returns the left-most child of node \f$i\f$
|
||||||
constexpr size_t left_most(size_t i) const {
|
constexpr size_t left_most(size_t i) const {
|
||||||
if (i >= _table.capacity()) return npos;
|
if (i >= _table.capacity()) return npos;
|
||||||
size_t n = i;
|
size_t n = i;
|
||||||
@@ -273,7 +273,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param i the node to start at
|
/// \param i the node to start at
|
||||||
/// \returns the right-most child of node `i`
|
/// \returns the right-most child of node \f$i\f$
|
||||||
constexpr size_t right_most(size_t i) const {
|
constexpr size_t right_most(size_t i) const {
|
||||||
if (i >= _table.capacity()) return npos;
|
if (i >= _table.capacity()) return npos;
|
||||||
if ((i = child(i)) == npos) {
|
if ((i = child(i)) == npos) {
|
||||||
@@ -308,7 +308,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The next node id were `insert` or `emplace` to be called
|
/// \returns The next node id were \f$insert\f$ or \f$emplace\f$ to be called
|
||||||
constexpr size_t next_id() const {
|
constexpr size_t next_id() const {
|
||||||
size_t i = _size;
|
size_t i = _size;
|
||||||
if (not _freed.empty()) {
|
if (not _freed.empty()) {
|
||||||
@@ -335,8 +335,8 @@ public:
|
|||||||
// Insertion & Deletion ================================================================================================
|
// Insertion & Deletion ================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Insertion, creates a node in the tree with parent `parent`
|
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||||
/// \param parent the parent node, if `npos` sets the value of the root node
|
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||||
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
||||||
/// \param val the value to insert
|
/// \param val the value to insert
|
||||||
/// \returns the index of the created node
|
/// \returns the index of the created node
|
||||||
@@ -345,8 +345,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Insertion, creates a node in the tree with parent `parent`
|
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||||
/// \param parent the parent node, if `npos` sets the value of the root node
|
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||||
/// \param next the next node, as an index relative to the parent
|
/// \param next the next node, as an index relative to the parent
|
||||||
/// \param val the value to insert
|
/// \param val the value to insert
|
||||||
/// \returns the index of the created node
|
/// \returns the index of the created node
|
||||||
@@ -354,6 +354,12 @@ public:
|
|||||||
return this->_insert(parent, next, fennec::forward<value_t>(val));
|
return this->_insert(parent, next, fennec::forward<value_t>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief tree insertion, copies the contents of tree into self with the root at the specified node location
|
||||||
|
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||||
|
/// \param next the next node, as an index relative to the parent
|
||||||
|
/// \param tree the tree to insert
|
||||||
|
/// \returns the index of the inserted root
|
||||||
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
|
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
|
||||||
list<pair<size_t, size_t>> visit;
|
list<pair<size_t, size_t>> visit;
|
||||||
visit.push_front({ root, parent });
|
visit.push_front({ root, parent });
|
||||||
@@ -378,8 +384,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Insertion, creates a node in the tree with parent `parent`
|
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||||
/// \param parent the parent node, if `npos` sets the value of the root node
|
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||||
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
|
||||||
/// \param args the args to construct the value to insert
|
/// \param args the args to construct the value to insert
|
||||||
/// \returns the index of the created node
|
/// \returns the index of the created node
|
||||||
@@ -426,7 +432,7 @@ public:
|
|||||||
/// \brief Traverse the tree using a specified order and visiting functor
|
/// \brief Traverse the tree using a specified order and visiting functor
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// The visitor should accept a reference to a value of type `TypeT` and a `size_t` which contains the node's id.
|
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a `size_t` which contains the node's id.
|
||||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||||
///
|
///
|
||||||
/// \tparam OrderT The order with which to traverse the tree.
|
/// \tparam OrderT The order with which to traverse the tree.
|
||||||
@@ -449,15 +455,25 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser pattern for breadth-first traversal
|
||||||
struct breadth_first {
|
struct breadth_first {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const rdtree&, size_t start) {
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \param mode The mode specifying branch conditions
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -483,17 +499,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser pattern for pre-order traversal
|
||||||
struct pre_order {
|
struct pre_order {
|
||||||
list<size_t> visit;
|
|
||||||
size_t head;
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const rdtree&, size_t start) {
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \param mode The mode specifying branch conditions
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -519,17 +549,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct in_order {
|
private:
|
||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser pattern for in-order traversal
|
||||||
|
struct in_order {
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -557,17 +601,31 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct post_order {
|
private:
|
||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser pattern for post-order traversal
|
||||||
|
struct post_order {
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traversal Init
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param start The node in the tree to start at
|
||||||
|
/// \returns The first index of the specified order
|
||||||
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverser Step
|
||||||
|
/// \param tree The tree we are operating on
|
||||||
|
/// \param node The current node
|
||||||
|
/// \returns The next index according to the traversal order
|
||||||
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
@@ -593,10 +651,14 @@ public:
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
allocation<node, alloc_t> _table;
|
allocation<node, alloc_t> _table;
|
||||||
list<size_t> _freed;
|
list<size_t> _freed;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|||||||
@@ -30,15 +30,9 @@
|
|||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_SEQUENCE_H
|
#ifndef FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
#define FENNEC_CONTAINERS_SEQUENCE_H
|
#define FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
#include <fennec/containers/bintree.h>
|
|
||||||
#include <fennec/containers/bintree.h>
|
|
||||||
#include <fennec/containers/pair.h>
|
#include <fennec/containers/pair.h>
|
||||||
#include <fennec/containers/sequence.h>
|
#include <fennec/containers/sequence.h>
|
||||||
#include <fennec/containers/sequence.h>
|
|
||||||
#include <fennec/containers/sequence.h>
|
|
||||||
#include <fennec/containers/sequence.h>
|
|
||||||
#include <fennec/containers/sequence.h>
|
|
||||||
#include <fennec/containers/sequence.h>
|
|
||||||
#include <fennec/lang/compare.h>
|
#include <fennec/lang/compare.h>
|
||||||
#include <fennec/memory/allocator.h>
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
@@ -64,13 +58,13 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
/// |:----------:|:---------------:|
|
/// |:----------:|:---------------:|
|
||||||
/// | stable | ⛔ |
|
/// | stable | ✅ |
|
||||||
/// | dynamic | ✅ |
|
/// | dynamic | ✅ |
|
||||||
/// | homogenous | ✅ |
|
/// | homogenous | ✅ |
|
||||||
/// | distinct | ✅ |
|
/// | distinct | ✅ |
|
||||||
/// | ordered | ✅ |
|
/// | ordered | ✅ |
|
||||||
/// | space | \f$O(N)\f$ |
|
/// | space | \f$O(N)\f$ |
|
||||||
/// | linear | ✅ |
|
/// | linear | ✅ |
|
||||||
/// | access | \f$O(\log N)\f$ |
|
/// | access | \f$O(\log N)\f$ |
|
||||||
/// | find | \f$O(\log N)\f$ |
|
/// | find | \f$O(\log N)\f$ |
|
||||||
/// | insertion | \f$O(\log N)\f$ |
|
/// | insertion | \f$O(\log N)\f$ |
|
||||||
@@ -83,15 +77,9 @@ template<typename TypeT, typename CompareT = less<TypeT>, class AllocT = allocat
|
|||||||
struct sequence {
|
struct sequence {
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
protected:
|
private:
|
||||||
struct _node;
|
struct _node;
|
||||||
|
|
||||||
public:
|
|
||||||
using value_t = TypeT;
|
|
||||||
using node_t = pair<TypeT, bool>;
|
|
||||||
using alloc_t = allocator_traits<AllocT>::template rebind<_node>;
|
|
||||||
using compare_t = CompareT;
|
|
||||||
|
|
||||||
enum color_ : bool {
|
enum color_ : bool {
|
||||||
black = false,
|
black = false,
|
||||||
red = true,
|
red = true,
|
||||||
@@ -102,9 +90,16 @@ public:
|
|||||||
dir_right = true,
|
dir_right = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
class iterator;
|
public:
|
||||||
|
using value_t = TypeT; //!< the value type
|
||||||
|
using node_t = pair<TypeT, bool>; //!< the node type
|
||||||
|
using alloc_t = allocator_traits<AllocT>::template rebind<_node>; //!< underlying alloc type
|
||||||
|
using compare_t = CompareT; //!< comparison type
|
||||||
|
|
||||||
protected:
|
class iterator;
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
using node = _node*;
|
using node = _node*;
|
||||||
|
|
||||||
struct _node {
|
struct _node {
|
||||||
@@ -246,7 +241,7 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Value Find Function, finds the iterator position for `val`, otherwise returns `end()`
|
/// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns `end()`
|
||||||
/// \param val The value to find
|
/// \param val The value to find
|
||||||
/// \returns An iterator at the value
|
/// \returns An iterator at the value
|
||||||
constexpr iterator find(const value_t& val) {
|
constexpr iterator find(const value_t& val) {
|
||||||
@@ -266,7 +261,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Value Contains Function, checks if the sequence contains a value
|
/// \brief Value Contains Function, checks if the sequence contains a value
|
||||||
/// \param val The value to find
|
/// \param val The value to find
|
||||||
/// \returns `true` if `val` is in the sequence, `false` otherwise
|
/// \returns \f$true\f$ if \f$val\f$ is in the sequence, \f$false\f$ otherwise
|
||||||
bool contains(const value_t& val) {
|
bool contains(const value_t& val) {
|
||||||
return find(val) != end();
|
return find(val) != end();
|
||||||
}
|
}
|
||||||
@@ -286,7 +281,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no elements in the sequence, `false` otherwise.
|
/// \returns \f$true\f$ when there are no elements in the sequence, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
@@ -299,7 +294,7 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Insertion, moves `val` into the sequence
|
/// \brief Move Insertion, moves \f$val\f$ into the sequence
|
||||||
/// \param val The value to insert
|
/// \param val The value to insert
|
||||||
constexpr void insert(value_t&& val) {
|
constexpr void insert(value_t&& val) {
|
||||||
node i = _insert_bst(fennec::forward<value_t>(val));
|
node i = _insert_bst(fennec::forward<value_t>(val));
|
||||||
@@ -307,7 +302,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Insertion, inserts a copy of `val` into the sequence
|
/// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence
|
||||||
/// \param val The value to insert
|
/// \param val The value to insert
|
||||||
constexpr void insert(const value_t& val) {
|
constexpr void insert(const value_t& val) {
|
||||||
node i = _insert_bst(val);
|
node i = _insert_bst(val);
|
||||||
@@ -324,6 +319,9 @@ public:
|
|||||||
_fix_insert(i);
|
_fix_insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Erase the specified value from the sequence
|
||||||
|
/// \param val the value to erase
|
||||||
constexpr void erase(const value_t& val) {
|
constexpr void erase(const value_t& val) {
|
||||||
_erase(find(val)._node);
|
_erase(find(val)._node);
|
||||||
}
|
}
|
||||||
@@ -336,7 +334,7 @@ public:
|
|||||||
visit.push_back(it._node);
|
visit.push_back(it._node);
|
||||||
}
|
}
|
||||||
for (node n : visit) {
|
for (node n : visit) {
|
||||||
_free_node(n);
|
this->_free_node(n);
|
||||||
}
|
}
|
||||||
_root = nullptr;
|
_root = nullptr;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
@@ -352,21 +350,35 @@ public:
|
|||||||
return sequence::iterator(this, _root);
|
return sequence::iterator(this, _root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns An iterator at the smallest element in the sequence
|
||||||
|
constexpr const_iterator begin() const {
|
||||||
|
return sequence::const_iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns An iterator after the largest element in the sequence
|
/// \returns An iterator after the largest element in the sequence
|
||||||
constexpr iterator end() {
|
constexpr iterator end() {
|
||||||
return sequence::iterator(this, _root, nullptr);
|
return sequence::iterator(this, _root, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Const C++ Iterator Specification `end()`
|
||||||
|
/// \returns An iterator after the largest element in the sequence
|
||||||
|
constexpr const_iterator end() const {
|
||||||
|
return sequence::const_iterator(this, _root, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
class iterator {
|
class iterator {
|
||||||
protected:
|
private:
|
||||||
sequence* _seq;
|
sequence* _seq;
|
||||||
node _head;
|
node _head;
|
||||||
node _node;
|
node _node;
|
||||||
list<node> _visit;
|
list<node> _visit;
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr iterator(sequence* seq, node start)
|
constexpr iterator(sequence* seq, node start)
|
||||||
: _seq(seq)
|
: _seq(seq)
|
||||||
, _head(start)
|
, _head(start)
|
||||||
@@ -379,49 +391,178 @@ public:
|
|||||||
, _node(start) {
|
, _node(start) {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator& operator++() {
|
public:
|
||||||
if (_node == nullptr) {
|
|
||||||
return *this;
|
///
|
||||||
|
/// \brief prefix increment operator
|
||||||
|
/// \param it the iterator to increment
|
||||||
|
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||||
|
friend iterator& operator++(iterator& it) {
|
||||||
|
if (it._node == nullptr) {
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
node parent = _seq->_parent(_node);
|
node parent = it._seq->_parent(it._node);
|
||||||
node pright = _seq->right(parent);
|
node pright = it._seq->right(parent);
|
||||||
node next = _seq->leftmost(_seq->right(_node));
|
node next = it._seq->leftmost(it._seq->right(it._node));
|
||||||
|
|
||||||
if (_node != pright && parent != nullptr) {
|
if (it._node != pright && parent != nullptr) {
|
||||||
_visit.push_front(parent);
|
it._visit.push_front(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next != nullptr) {
|
if (next != nullptr) {
|
||||||
_visit.push_front(next);
|
it._visit.push_front(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not _visit.empty()) {
|
if (not it._visit.empty()) {
|
||||||
_node = _visit.front();
|
it._node = it._visit.front();
|
||||||
_visit.pop_front();
|
it._visit.pop_front();
|
||||||
} else {
|
} else {
|
||||||
_node = nullptr;
|
it._node = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator operator++(int) {
|
///
|
||||||
iterator prev = *this;
|
/// \brief postfix increment operator
|
||||||
this->operator++();
|
/// \param it the iterator to increment
|
||||||
|
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||||
|
friend iterator operator++(iterator& it, int) {
|
||||||
|
iterator prev = it;
|
||||||
|
++it;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
const value_t& operator*() const {
|
const value_t& operator*() const {
|
||||||
return _node->key;
|
return _node->key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
const value_t* operator->() const {
|
const value_t* operator->() const {
|
||||||
return &_node->key;
|
return &_node->key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param lhs the iterator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
constexpr friend bool operator==(const iterator& lhs, const iterator& rhs) {
|
constexpr friend bool operator==(const iterator& lhs, const iterator& rhs) {
|
||||||
return lhs._node == rhs._node;
|
return lhs._seq == rhs._seq and lhs._node == rhs._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param lhs the iterator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
|
constexpr friend bool operator!=(const iterator& lhs, const iterator& rhs) {
|
||||||
|
return lhs._seq != rhs._seq or lhs._node != rhs._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend struct sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
|
class const_iterator {
|
||||||
|
private:
|
||||||
|
const sequence* _seq;
|
||||||
|
node _head;
|
||||||
|
node _node;
|
||||||
|
list<node> _visit;
|
||||||
|
|
||||||
|
constexpr const_iterator(const sequence* seq, node start)
|
||||||
|
: _seq(seq)
|
||||||
|
, _head(start)
|
||||||
|
, _node(seq->leftmost(start)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_iterator(const sequence* seq, node root, node start)
|
||||||
|
: _seq(seq)
|
||||||
|
, _head(root)
|
||||||
|
, _node(start) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief prefix increment operator
|
||||||
|
/// \param it the iterator to increment
|
||||||
|
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||||
|
friend const_iterator& operator++(const_iterator& it) {
|
||||||
|
if (it._node == nullptr) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
node parent = it._seq->_parent(it._node);
|
||||||
|
node pright = it._seq->right(parent);
|
||||||
|
node next = it._seq->leftmost(it._seq->right(it._node));
|
||||||
|
|
||||||
|
if (it._node != pright && parent != nullptr) {
|
||||||
|
it._visit.push_front(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next != nullptr) {
|
||||||
|
it._visit.push_front(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not it._visit.empty()) {
|
||||||
|
it._node = it._visit.front();
|
||||||
|
it._visit.pop_front();
|
||||||
|
} else {
|
||||||
|
it._node = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \param it the iterator to increment
|
||||||
|
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||||
|
friend const_iterator operator++(const_iterator& it, int) {
|
||||||
|
const_iterator prev = it;
|
||||||
|
++it;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return _node->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &_node->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param lhs the iterator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
|
constexpr friend bool operator==(const const_iterator& lhs, const const_iterator& rhs) {
|
||||||
|
return lhs._seq == rhs._seq and lhs._node == rhs._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param lhs the iterator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
|
constexpr friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs) {
|
||||||
|
return lhs._seq != rhs._seq or lhs._node != rhs._node;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend struct sequence;
|
friend struct sequence;
|
||||||
@@ -429,14 +570,14 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// Fields ==============================================================================================================
|
// Fields ==============================================================================================================
|
||||||
protected:
|
private:
|
||||||
alloc_t _alloc;
|
alloc_t _alloc;
|
||||||
node _root;
|
node _root;
|
||||||
compare_t _compare;
|
compare_t _compare;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|
||||||
// Helpers =============================================================================================================
|
// Helpers =============================================================================================================
|
||||||
protected:
|
private:
|
||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr node _make_node(ArgsT&&...args) {
|
constexpr node _make_node(ArgsT&&...args) {
|
||||||
|
|||||||
@@ -69,14 +69,13 @@ struct set {
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>;
|
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>; //!< the allocator type
|
||||||
using hash_t = Hash;
|
using hash_t = Hash; //!< the hash type
|
||||||
using equal_t = Equals;
|
using equal_t = Equals; //!< the equality type
|
||||||
using elem_t = TypeT;
|
using elem_t = TypeT; //!< the element type
|
||||||
|
|
||||||
|
static constexpr double default_load = 0.8; //!< the default load factor for reallocation
|
||||||
class iterator;
|
class iterator;
|
||||||
static constexpr size_t npos = -1;
|
|
||||||
static constexpr double default_load = 0.8;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct node {
|
struct node {
|
||||||
@@ -87,6 +86,8 @@ private:
|
|||||||
constexpr ~node() = default;
|
constexpr ~node() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when the set is empty, `false` otherwise
|
/// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
@@ -252,7 +253,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Check if a set contains a value
|
/// \brief Check if a set contains a value
|
||||||
/// \param val Value to check
|
/// \param val Value to check
|
||||||
/// \returns `true` if `val` can be found, `false` otherwise
|
/// \returns \f$true\f$ if \f$val\f$ can be found, \f$false\f$ otherwise
|
||||||
constexpr bool contains(const elem_t& val) const {
|
constexpr bool contains(const elem_t& val) const {
|
||||||
return this->find(val) != end();
|
return this->find(val) != end();
|
||||||
}
|
}
|
||||||
@@ -260,7 +261,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Iterator Access
|
/// \brief Iterator Access
|
||||||
/// \param it Location to access
|
/// \param it Location to access
|
||||||
/// \returns A pointer to the element, `nullptr` if not found.
|
/// \returns A pointer to the element, \f$nullptr\f$ if not found.
|
||||||
/// The value should not be changed in a manner that will change the hash of the element.
|
/// The value should not be changed in a manner that will change the hash of the element.
|
||||||
constexpr elem_t* at(const iterator& it) {
|
constexpr elem_t* at(const iterator& it) {
|
||||||
if (it == end()) {
|
if (it == end()) {
|
||||||
@@ -275,7 +276,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Iterator Const Access
|
/// \brief Iterator Const Access
|
||||||
/// \param it Location to access
|
/// \param it Location to access
|
||||||
/// \returns A const-qualified pointer to the element, `nullptr` if not found.
|
/// \returns A const-qualified pointer to the element, \f$nullptr\f$ if not found.
|
||||||
constexpr const elem_t* at(const iterator& it) const {
|
constexpr const elem_t* at(const iterator& it) const {
|
||||||
if (not _alloc[it._i].value) return nullptr;
|
if (not _alloc[it._i].value) return nullptr;
|
||||||
return &*_alloc[it._i].value;
|
return &*_alloc[it._i].value;
|
||||||
@@ -347,11 +348,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief
|
/// \brief Clear all elements from the set, destructing them
|
||||||
constexpr void clear() {
|
constexpr void clear() {
|
||||||
for (size_t i = 0; i < _alloc.capacity(); ++i) {
|
_alloc.clear();
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -381,57 +380,79 @@ public:
|
|||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Class for Iterating the Set
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
class iterator {
|
class iterator {
|
||||||
public:
|
public:
|
||||||
constexpr iterator(const set* set, size_t i)
|
///
|
||||||
: _set(set)
|
/// \brief destructor
|
||||||
, _i(i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ~iterator() {
|
constexpr ~iterator() {
|
||||||
_set = nullptr;
|
_set = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix operator
|
///
|
||||||
constexpr friend iterator& operator++(iterator& rhs) {
|
/// \brief prefix increment operator
|
||||||
while (++rhs._i < rhs._set->capacity()) {
|
/// \param it the iterator to increment
|
||||||
if (rhs._set->_alloc[rhs._i].value) {
|
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||||
return rhs;
|
constexpr friend iterator& operator++(iterator& it) {
|
||||||
|
while (++it._i < it._set->capacity()) {
|
||||||
|
if (it._set->_alloc[it._i].value) {
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rhs._i = npos;
|
it._i = npos;
|
||||||
return rhs;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend iterator operator++(iterator& lhs, int) {
|
///
|
||||||
iterator prev = lhs;
|
/// \brief postfix increment operator
|
||||||
++lhs;
|
/// \param it the iterator to increment
|
||||||
|
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||||
|
constexpr friend iterator operator++(iterator& it, int) {
|
||||||
|
iterator prev = it;
|
||||||
|
++it;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns a reference to the value pointed by the iterator
|
||||||
constexpr const elem_t& operator*() const {
|
constexpr const elem_t& operator*() const {
|
||||||
return *_set->_alloc[_i].value;
|
return *_set->_alloc[_i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief pointer access operator
|
||||||
|
/// \returns a pointer to the value pointed by the iterator
|
||||||
constexpr const elem_t* operator->() const {
|
constexpr const elem_t* operator->() const {
|
||||||
if (not _set->_alloc[_i].value) return nullptr;
|
if (not _set->_alloc[_i].value) return nullptr;
|
||||||
return &*_set->_alloc[_i].value;
|
return &*_set->_alloc[_i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
constexpr bool operator==(const iterator& it) const {
|
constexpr bool operator==(const iterator& it) const {
|
||||||
return _set == it._set and _i == it._i;
|
return _set == it._set and _i == it._i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param it the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
constexpr bool operator!=(const iterator& it) const {
|
constexpr bool operator!=(const iterator& it) const {
|
||||||
return _set != it._set or _i != it._i;
|
return _set != it._set or _i != it._i;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t index() const { return _i; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const set* _set;
|
const set* _set;
|
||||||
size_t _i;
|
size_t _i;
|
||||||
|
|
||||||
|
constexpr iterator(const set* set, size_t i)
|
||||||
|
: _set(set)
|
||||||
|
, _i(i) {
|
||||||
|
}
|
||||||
|
|
||||||
friend set;
|
friend set;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -42,24 +42,29 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// \brief Tuple, holds a collection of values of different types
|
/// \brief Tuple, holds a collection of values of different types
|
||||||
/// \details
|
/// \details
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
/// |:----------:|:----------:|
|
/// |:----------:|:-----------:|
|
||||||
/// | stable | ⛔ |
|
/// | stable | ⛔ |
|
||||||
/// | dynamic | ✅ |
|
/// | dynamic | ✅ |
|
||||||
/// | homogenous | ⛔ |
|
/// | homogenous | ⛔ |
|
||||||
/// | distinct | ⛔ |
|
/// | distinct | ⛔ |
|
||||||
/// | ordered | ⛔ |
|
/// | ordered | ⛔ |
|
||||||
/// | space | \f$O(N)\f$ |
|
/// | space | \f$O(N)\f$ |
|
||||||
/// | linear | ✅ |
|
/// | linear | ✅ |
|
||||||
/// | access | \f$O(1)\f$ |
|
/// | access | \f$O(1)\f$ |
|
||||||
/// | find | \f$O(1)\f$ |
|
/// | find | \f$O(1)\f$ |
|
||||||
/// | insertion | ⛔ |
|
/// | insertion | ⛔ |
|
||||||
/// | deletion | ⛔ |
|
/// | deletion | ⛔ |
|
||||||
///
|
///
|
||||||
/// \tparam TypesT The types to store
|
/// \tparam TypesT The types to store
|
||||||
template<typename...TypesT> struct tuple;
|
template<typename...TypesT> struct tuple;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief tuple get
|
||||||
|
/// \tparam i the index
|
||||||
|
/// \tparam TypesT the types held in the tuple
|
||||||
|
/// \param x the tuple
|
||||||
|
/// \returns the \f$i\f$th element of the tuple
|
||||||
template<size_t i, typename...TypesT>
|
template<size_t i, typename...TypesT>
|
||||||
constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
|
constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
|
||||||
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
||||||
@@ -67,6 +72,11 @@ constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x
|
|||||||
return it.value;
|
return it.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \tparam i the index
|
||||||
|
/// \tparam TypesT the types held in the tuple
|
||||||
|
/// \param x the tuple
|
||||||
|
/// \returns the \f$i\f$th element of the tuple
|
||||||
template<size_t i, typename...TypesT>
|
template<size_t i, typename...TypesT>
|
||||||
constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<TypesT...>& x) {
|
constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<TypesT...>& x) {
|
||||||
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
||||||
@@ -78,28 +88,41 @@ constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<T
|
|||||||
template<typename ...TypesT>
|
template<typename ...TypesT>
|
||||||
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>
|
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>
|
||||||
{
|
{
|
||||||
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>;
|
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type
|
||||||
|
|
||||||
template<size_t i>
|
template<size_t i>
|
||||||
using elem_t = typename nth_element<i, TypesT...>::type;
|
using elem_t = typename nth_element<i, TypesT...>::type; //!< helper for getting the \f$i\f$th element
|
||||||
|
|
||||||
static constexpr size_t size = sizeof...(TypesT);
|
static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief tuple constructor
|
||||||
|
/// \tparam ArgsT The element types
|
||||||
|
/// \param args The arguments to initialize the tuple with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
tuple(ArgsT&&...args)
|
tuple(ArgsT&&...args)
|
||||||
: base_t(fennec::forward<ArgsT>(args)...) {
|
: base_t(fennec::forward<ArgsT>(args)...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief copy constructor
|
||||||
|
/// \param cpy the tuple to copy
|
||||||
tuple(const tuple& cpy)
|
tuple(const tuple& cpy)
|
||||||
: base_t(cpy) {
|
: base_t(cpy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple(tuple&& cpy)
|
///
|
||||||
: base_t(cpy) {
|
/// \brief move constructor
|
||||||
|
/// \param mov the tuple to move
|
||||||
|
tuple(tuple&& mov)
|
||||||
|
: base_t(mov) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is needed for
|
///
|
||||||
|
/// \brief Helper for deducing the tuple constructor
|
||||||
|
/// \tparam TypesT the types of the tuple
|
||||||
|
/// \returns A new tuple containing the passed values
|
||||||
template<typename...TypesT>
|
template<typename...TypesT>
|
||||||
tuple(TypesT...) -> tuple<TypesT...>;
|
tuple(TypesT...) -> tuple<TypesT...>;
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ struct variant {
|
|||||||
|
|
||||||
// Typedefs & Constants ================================================================================================
|
// Typedefs & Constants ================================================================================================
|
||||||
|
|
||||||
static constexpr size_t size = max_element_size_v<TypesT...>;
|
static constexpr size_t size = max_element_size_v<TypesT...>; //!< size of the variant in bytes
|
||||||
static constexpr size_t nulltype = sizeof...(TypesT);
|
static constexpr size_t nulltype = sizeof...(TypesT); //!< id for a null type
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -74,8 +74,8 @@ struct variant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Conversion Constructor, constructs the type in `TypesT...` that is identical to `T`
|
/// \brief Conversion Constructor, constructs the type in `TypesT...` that is identical to \f$T\f$
|
||||||
/// or the first that is constructible with `T`
|
/// or the first that is constructible with \f$T\f$
|
||||||
/// \tparam T The type of the value
|
/// \tparam T The type of the value
|
||||||
/// \param t The value to forward
|
/// \param t The value to forward
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -146,10 +146,15 @@ struct variant {
|
|||||||
|
|
||||||
// Assignment ==========================================================================================================
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief value assignment operator
|
||||||
|
/// \tparam T The type to assign
|
||||||
|
/// \param t the value to assign
|
||||||
|
/// \returns a reference to \f$self\f$ after assigning \f$t\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
variant& operator=(T&& t) {
|
variant& operator=(T&& t) {
|
||||||
|
|
||||||
// First, check if `T` is in `TypesT...`
|
// First, check if \f$T\f$ is in `TypesT...`
|
||||||
if constexpr((contains_element_v<T, TypesT> or ...)) {
|
if constexpr((contains_element_v<T, TypesT> or ...)) {
|
||||||
using type_t = remove_reference_t<T>;
|
using type_t = remove_reference_t<T>;
|
||||||
if (_type == find_element_v<type_t, TypesT...>) {
|
if (_type == find_element_v<type_t, TypesT...>) {
|
||||||
@@ -182,12 +187,21 @@ struct variant {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief emplace function
|
||||||
|
/// \tparam T The type to construct
|
||||||
|
/// \tparam ArgsT the argument types
|
||||||
|
/// \param args the argument values
|
||||||
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
||||||
void emplace(ArgsT&&...args) {
|
void emplace(ArgsT&&...args) {
|
||||||
_clear();
|
_clear();
|
||||||
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief deduced emplace function
|
||||||
|
/// \tparam ArgsT the argument types
|
||||||
|
/// \param args the argument values
|
||||||
template<size_t I, typename...ArgsT>
|
template<size_t I, typename...ArgsT>
|
||||||
void emplace(ArgsT&&...args) {
|
void emplace(ArgsT&&...args) {
|
||||||
using type_t = nth_element_t<I, TypesT...>;
|
using type_t = nth_element_t<I, TypesT...>;
|
||||||
@@ -198,21 +212,34 @@ struct variant {
|
|||||||
|
|
||||||
// Access ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief get the value of the variant interpreted as \f$T\f$
|
||||||
|
/// \tparam T the type to interpret as
|
||||||
|
/// \returns The value interpreted as \f$T\f$
|
||||||
template<typename T> requires(contains_element_v<T, TypesT...>)
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
T& get() {
|
T& get() {
|
||||||
return *static_cast<T*>(_handle);
|
return *static_cast<T*>(_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \tparam T the type to interpret as
|
||||||
|
/// \returns The value interpreted as \f$T\f$
|
||||||
template<typename T> requires(contains_element_v<T, TypesT...>)
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
const T& get() const {
|
const T& get() const {
|
||||||
return *static_cast<T*>(_handle);
|
return *static_cast<T*>(_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \tparam T the type to interpret as
|
||||||
|
/// \returns The value interpreted as \f$T\f$
|
||||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
T& get() {
|
T& get() {
|
||||||
return *static_cast<T*>(_handle);
|
return *static_cast<T*>(_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \tparam T the type to interpret as
|
||||||
|
/// \returns The value interpreted as \f$T\f$
|
||||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
const T& get() const {
|
const T& get() const {
|
||||||
return *static_cast<T*>(_handle);
|
return *static_cast<T*>(_handle);
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ struct event;
|
|||||||
class event_listener {
|
class event_listener {
|
||||||
public:
|
public:
|
||||||
virtual ~event_listener() = default;
|
virtual ~event_listener() = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief event handler callback
|
||||||
|
/// \param event the event to handle
|
||||||
virtual void handle_event(event* event) = 0;
|
virtual void handle_event(event* event) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,25 +48,42 @@ struct event {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Registers a listener for the event type
|
/// \brief Registers a listener for the event type
|
||||||
/// \tparam EventT
|
/// \tparam EventT the event type
|
||||||
/// \param listener
|
/// \param listener the listener to register
|
||||||
template<typename EventT>
|
template<typename EventT>
|
||||||
static void add_listener(event_listener* listener) {
|
static void add_listener(event_listener* listener) {
|
||||||
event::add_listener(listener, typeuuid<EventT, event>());
|
event::add_listener(listener, typeuuid<EventT, event>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Add a listener for an event type of \f$type\f$
|
||||||
|
/// \param listener the listener to add
|
||||||
|
/// \param type the event type to listen for
|
||||||
|
static void add_listener(event_listener* listener, uint64_t type);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief removes a listener from the event system
|
||||||
|
/// \param listener the listener to remove
|
||||||
|
static void remove_listener(event_listener* listener);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Dispatch an event
|
||||||
|
/// \tparam EventT The event type
|
||||||
|
/// \param event the event to dispatch
|
||||||
template<typename EventT>
|
template<typename EventT>
|
||||||
static void dispatch(EventT* event) {
|
static void dispatch(EventT* event) {
|
||||||
dispatch(event);
|
event::dispatch(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_listener(event_listener* listener, uint64_t type);
|
///
|
||||||
static void remove_listener(event_listener* listener);
|
/// \brief Dispatch an event
|
||||||
|
/// \param event the event to dispatch
|
||||||
static void dispatch(event* event);
|
static void dispatch(event* event);
|
||||||
|
|
||||||
|
#ifndef FENNEC_DOXYGEN
|
||||||
FENNEC_RTTI_CLASS_ENABLE() {
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,23 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief logger class
|
||||||
class logger : public singleton<logger> {
|
class logger : public singleton<logger> {
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief default constructor
|
||||||
logger();
|
logger();
|
||||||
~logger();
|
~logger();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Log a string to the log file and cout
|
||||||
|
/// \param str the string to log
|
||||||
|
/// \param _line the line of the log call
|
||||||
|
/// \param _file the file log was called in
|
||||||
static void log(const cstring& str,
|
static void log(const cstring& str,
|
||||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
const char* _file = FENNEC_BUILTIN_FILE()
|
const char* _file = FENNEC_BUILTIN_FILE()
|
||||||
) {
|
) {
|
||||||
logger& inst = instance();
|
logger& inst = instance();
|
||||||
|
|
||||||
@@ -61,6 +70,11 @@ public:
|
|||||||
inst._cout->println(str);
|
inst._cout->println(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Log a string to the log file and cout
|
||||||
|
/// \param str the string to log
|
||||||
|
/// \param _line the line of the log call
|
||||||
|
/// \param _file the file log was called in
|
||||||
static void log(const string& str,
|
static void log(const string& str,
|
||||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
const char* _file = FENNEC_BUILTIN_FILE()
|
const char* _file = FENNEC_BUILTIN_FILE()
|
||||||
|
|||||||
@@ -38,9 +38,13 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief simple version struct for drivers and systems
|
||||||
struct version {
|
struct version {
|
||||||
uint32_t major, minor, patch;
|
uint32_t major; //!< the major version
|
||||||
string str;
|
uint32_t minor; //!< the minor version
|
||||||
|
uint32_t patch; //!< the patch
|
||||||
|
string str; //!< string representation of the version
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ namespace fennec
|
|||||||
/// <tr><th style="vertical-align: top">Flags
|
/// <tr><th style="vertical-align: top">Flags
|
||||||
/// <th style="vertical-align: top">Description
|
/// <th style="vertical-align: top">Description
|
||||||
///
|
///
|
||||||
/// <tr><td style="vertical-align: top">`read`
|
/// <tr><td style="vertical-align: top">\f$read\f$
|
||||||
/// <td style="vertical-align: top">Opens file as read-only, reading from start
|
/// <td style="vertical-align: top">Opens file as read-only, reading from start
|
||||||
///
|
///
|
||||||
/// <tr><td style="vertical-align: top">`write`
|
/// <tr><td style="vertical-align: top">\f$write\f$
|
||||||
/// <td style="vertical-align: top">Opens file as write-only, writing to end
|
/// <td style="vertical-align: top">Opens file as write-only, writing to end
|
||||||
///
|
///
|
||||||
/// <tr><td style="vertical-align: top">`read | write`
|
/// <tr><td style="vertical-align: top">`read | write`
|
||||||
@@ -109,16 +109,28 @@ public:
|
|||||||
/// \brief default constructor, initializes an empty stream
|
/// \brief default constructor, initializes an empty stream
|
||||||
file();
|
file();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
|
||||||
|
/// \param path the path of the file
|
||||||
|
/// \param mode the mode to open with
|
||||||
file(const cstring& path, uint8_t mode)
|
file(const cstring& path, uint8_t mode)
|
||||||
: file() {
|
: file() {
|
||||||
open(path, mode);
|
open(path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
|
||||||
|
/// \param path the path of the file
|
||||||
|
/// \param mode the mode to open with
|
||||||
file(const string& path, uint8_t mode)
|
file(const string& path, uint8_t mode)
|
||||||
: file() {
|
: file() {
|
||||||
open(path, mode);
|
open(path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
|
||||||
|
/// \param path the path of the file
|
||||||
|
/// \param mode the mode to open with
|
||||||
file(const path& path, uint8_t mode)
|
file(const path& path, uint8_t mode)
|
||||||
: file() {
|
: file() {
|
||||||
open(path, mode);
|
open(path, mode);
|
||||||
@@ -133,6 +145,9 @@ public:
|
|||||||
/// \param file the stream to take ownership of
|
/// \param file the stream to take ownership of
|
||||||
file(file&& file) noexcept;
|
file(file&& file) noexcept;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move assignment
|
||||||
|
/// \param file the stream to take ownership of
|
||||||
file& operator=(file&& file) noexcept;
|
file& operator=(file&& file) noexcept;
|
||||||
|
|
||||||
// don't allow copying streams
|
// don't allow copying streams
|
||||||
@@ -258,21 +273,52 @@ public:
|
|||||||
|
|
||||||
// File Positioning ====================================================================================================
|
// File Positioning ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the position index in the stream
|
||||||
size_t get_pos() const;
|
size_t get_pos() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param i the new index to move to
|
||||||
|
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||||
bool set_pos(size_t i);
|
bool set_pos(size_t i);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief return to the start of the stream
|
||||||
|
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||||
bool rewind();
|
bool rewind();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns \f$true\f$ if the stream has reached the end of the file, \f$false\f$ otherwise
|
||||||
bool eof() const;
|
bool eof() const;
|
||||||
|
|
||||||
|
|
||||||
// Binary Read Operations ==============================================================================================
|
// Binary Read Operations ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief binary read
|
||||||
|
/// \param data the buffer to write to
|
||||||
|
/// \param size the size of each object in bytes
|
||||||
|
/// \param n the number of objects to read
|
||||||
|
/// \returns the number of objects successfully read
|
||||||
size_t read(void* data, size_t size, size_t n);
|
size_t read(void* data, size_t size, size_t n);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief type read
|
||||||
|
/// \tparam T the type to read
|
||||||
|
/// \param data the buffer to write to
|
||||||
|
/// \param n the number of objects to read
|
||||||
|
/// \returns the number of objects successfully read
|
||||||
template<typename T>
|
template<typename T>
|
||||||
size_t read(T* data, size_t n) {
|
size_t read(T* data, size_t n) {
|
||||||
return read(static_cast<void*>(data), sizeof(T), n);
|
return read(static_cast<void*>(data), sizeof(T), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief type read
|
||||||
|
/// \tparam T the type to read
|
||||||
|
/// \tparam n the number of objects to read
|
||||||
|
/// \param data the buffer to write to
|
||||||
|
/// \returns the number of objects successfully read
|
||||||
template<typename T, size_t n>
|
template<typename T, size_t n>
|
||||||
size_t read(T (&data)[n]) {
|
size_t read(T (&data)[n]) {
|
||||||
return read(static_cast<void*>(data), sizeof(T), n);
|
return read(static_cast<void*>(data), sizeof(T), n);
|
||||||
@@ -281,26 +327,63 @@ public:
|
|||||||
|
|
||||||
// Binary Write Operations =============================================================================================
|
// Binary Write Operations =============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief put a character at the current position in the stream
|
||||||
|
/// \param c the character to put
|
||||||
|
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||||
bool putc(char c);
|
bool putc(char c);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief put a wide character at the current position in the stream
|
||||||
|
/// \param c the character to put
|
||||||
|
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||||
bool putwc(wchar_t c);
|
bool putwc(wchar_t c);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief write a buffer to at the current position in the stream
|
||||||
|
/// \param data the buffer to read from
|
||||||
|
/// \param size the size of each object in bytes
|
||||||
|
/// \param n the number of objects to write
|
||||||
|
/// \returns the number of objects successfully written
|
||||||
size_t write(const void* data, size_t size, size_t n);
|
size_t write(const void* data, size_t size, size_t n);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief write a character buffer to at the current position in the stream
|
||||||
|
/// \tparam n the number of characters to write
|
||||||
|
/// \param data the buffer to read from
|
||||||
|
/// \returns the number of objects successfully written
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
size_t write(const char (&data)[n]) {
|
size_t write(const char (&data)[n]) {
|
||||||
return write(data, sizeof(char), n - 1);
|
return write(data, sizeof(char), n - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief write a wide character buffer to at the current position in the stream
|
||||||
|
/// \tparam n the number of characters to write
|
||||||
|
/// \param data the buffer to read from
|
||||||
|
/// \returns the number of objects successfully written
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
size_t write(const wchar_t (&data)[n]) {
|
size_t write(const wchar_t (&data)[n]) {
|
||||||
return write(data, sizeof(wchar_t), n - 1);
|
return write(data, sizeof(wchar_t), n - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief write a buffer to at the current position in the stream
|
||||||
|
/// \tparam T the object type to write
|
||||||
|
/// \param data the buffer to read from
|
||||||
|
/// \param n the number of objects to write
|
||||||
|
/// \returns the number of objects successfully written
|
||||||
template<typename T>
|
template<typename T>
|
||||||
size_t write(const T* data, size_t n) {
|
size_t write(const T* data, size_t n) {
|
||||||
return write(static_cast<const void*>(data), sizeof(T), n);
|
return write(static_cast<const void*>(data), sizeof(T), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief write a buffer to at the current position in the stream
|
||||||
|
/// \tparam T the object type to write
|
||||||
|
/// \tparam n the number of objects to write
|
||||||
|
/// \param data the buffer to read from
|
||||||
|
/// \returns the number of objects successfully written
|
||||||
template<typename T, size_t n>
|
template<typename T, size_t n>
|
||||||
size_t write(const T (&data)[n]) {
|
size_t write(const T (&data)[n]) {
|
||||||
return write(static_cast<const void*>(data), sizeof(T), n);
|
return write(static_cast<const void*>(data), sizeof(T), n);
|
||||||
@@ -309,21 +392,48 @@ public:
|
|||||||
|
|
||||||
// Read Operations =====================================================================================================
|
// Read Operations =====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the character read at the current position in the stream
|
||||||
char getc();
|
char getc();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the wide character read at the current position in the stream
|
||||||
wchar_t getwc();
|
wchar_t getwc();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns a string containing all characters from the current position in the stream to the next newline character
|
||||||
string getline();
|
string getline();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns a string containing all characters from the current position in the stream to the next newline character
|
||||||
wstring getwline();
|
wstring getwline();
|
||||||
|
|
||||||
|
|
||||||
// Printing Operations =================================================================================================
|
// Printing Operations =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param str the string to print
|
||||||
void print(const cstring& str);
|
void print(const cstring& str);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief print a string to the stream
|
||||||
|
/// \param str the string to print
|
||||||
void print(const string& str);
|
void print(const string& str);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param str the string to print
|
||||||
void println(const cstring& str);
|
void println(const cstring& str);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief print a string to the stream followed by a newline character
|
||||||
|
/// \param str the string to print
|
||||||
void println(const string& str);
|
void println(const string& str);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief print a formatted string to the stream
|
||||||
|
/// \tparam ArgsT the argument types
|
||||||
|
/// \param str the format string
|
||||||
|
/// \param args the argument values
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
void printf(const cstring& str, ArgsT&&...args) {
|
void printf(const cstring& str, ArgsT&&...args) {
|
||||||
string fmt = fennec::format(str, fennec::forward<ArgsT>(args)...);
|
string fmt = fennec::format(str, fennec::forward<ArgsT>(args)...);
|
||||||
@@ -335,7 +445,12 @@ public:
|
|||||||
|
|
||||||
// Error Handling ======================================================================================================
|
// Error Handling ======================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the current error state of the file
|
||||||
const char* get_error() const { return _error; }
|
const char* get_error() const { return _error; }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief clears the errored state
|
||||||
void clear_error() { _error = nullptr; }
|
void clear_error() { _error = nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
|
|
||||||
class iterator;
|
class iterator;
|
||||||
friend iterator;
|
friend class iterator;
|
||||||
|
|
||||||
|
|
||||||
// Static Functions ====================================================================================================
|
// Static Functions ====================================================================================================
|
||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief C-String Assignment Operator
|
/// \brief C-String Assignment Operator
|
||||||
/// \param str the cstring to assign
|
/// \param str the cstring to assign
|
||||||
/// \returns a reference to `this` after assigning `p`
|
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
path& operator=(const char (&str)[n]) {
|
path& operator=(const char (&str)[n]) {
|
||||||
_str = str;
|
_str = str;
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief C-String Assignment Operator
|
/// \brief C-String Assignment Operator
|
||||||
/// \param p the cstring to assign
|
/// \param p the cstring to assign
|
||||||
/// \returns a reference to `this` after assigning `p`
|
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||||
path& operator=(const cstring& p) {
|
path& operator=(const cstring& p) {
|
||||||
_str = p;
|
_str = p;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -114,7 +114,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Assignment Operator
|
/// \brief String Assignment Operator
|
||||||
/// \param p the cstring to assign
|
/// \param p the cstring to assign
|
||||||
/// \returns a reference to `this` after assigning `p`
|
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||||
path& operator=(const string& p) {
|
path& operator=(const string& p) {
|
||||||
_str = p;
|
_str = p;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Path Copy Assignment Operator
|
/// \brief Path Copy Assignment Operator
|
||||||
/// \param p the path to copy
|
/// \param p the path to copy
|
||||||
/// \returns a reference to `this` after copying `p`
|
/// \returns a reference to \f$this\f$ after copying \f$p\f$
|
||||||
path& operator=(const path& p) {
|
path& operator=(const path& p) {
|
||||||
_str = p._str;
|
_str = p._str;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -132,7 +132,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Path Move Assignment Operator
|
/// \brief Path Move Assignment Operator
|
||||||
/// \param p the path to take ownership of
|
/// \param p the path to take ownership of
|
||||||
/// \returns a reference to `this` after taking ownership of `p`
|
/// \returns a reference to \f$this\f$ after taking ownership of \f$p\f$
|
||||||
path& operator=(path&& p) noexcept {
|
path& operator=(path&& p) noexcept {
|
||||||
_str = move(p._str);
|
_str = move(p._str);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -142,33 +142,55 @@ public:
|
|||||||
// Append Operators ====================================================================================================
|
// Append Operators ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief
|
/// \brief path append operator
|
||||||
/// \param str
|
/// \param str the filename to append
|
||||||
/// \return
|
/// \returns a path containing the current path followed by \f$str\f$
|
||||||
path operator/(const cstring& str) const {
|
path operator/(const cstring& str) const {
|
||||||
return path(_str + '/' + str);
|
return path(_str + '/' + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path append operator
|
||||||
|
/// \param str the filename to append
|
||||||
|
/// \returns a path containing the current path followed by \f$str\f$
|
||||||
path operator/(const string& str) const {
|
path operator/(const string& str) const {
|
||||||
return path(_str + '/' + str);
|
return path(_str + '/' + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path append operator
|
||||||
|
/// \param p the path to append
|
||||||
|
/// \returns a path containing the current path followed by \f$p\f$
|
||||||
path operator/(const path& p) const {
|
path operator/(const path& p) const {
|
||||||
return path(_str + '/' + p._str);
|
return path(_str + '/' + p._str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief path equality operator
|
||||||
|
/// \param p the path to compare against
|
||||||
|
/// \returns \f$true\f$ if the paths are identical, \f$false\f$ otherwise. relative paths are not resolved
|
||||||
bool operator==(const path& p) const {
|
bool operator==(const path& p) const {
|
||||||
return _str == p._str;
|
return _str == p._str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief the filename of the current path
|
||||||
|
/// \returns a string containing a copy of the filename
|
||||||
string filename() const {
|
string filename() const {
|
||||||
size_t i = _str.rfind('/');
|
size_t i = _str.rfind('/');
|
||||||
return _str.substring(i + 1);
|
return _str.substring(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the underlying string representation
|
||||||
const string& str() const { return _str; }
|
const string& str() const { return _str; }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the underlying C-Style string representation
|
||||||
const char* cstr() const { return _str.cstr(); }
|
const char* cstr() const { return _str.cstr(); }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns \f$true\f$ if the path is empty or points to root
|
||||||
bool empty() {
|
bool empty() {
|
||||||
size_t size = _str.size();
|
size_t size = _str.size();
|
||||||
if (size == 0) return true;
|
if (size == 0) return true;
|
||||||
@@ -179,6 +201,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns a copy of the path with the filename removed
|
||||||
path parent() const {
|
path parent() const {
|
||||||
#ifdef FENNEC_PLATFORM_WINDOWS
|
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||||
size_t start = _str.size() - 1;
|
size_t start = _str.size() - 1;
|
||||||
@@ -203,6 +227,9 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief absolute path
|
||||||
|
/// \returns a copy of the path with relative paths resolved
|
||||||
path absolute() const {
|
path absolute() const {
|
||||||
path parse = *this;
|
path parse = *this;
|
||||||
path working; working._str.resize(0);
|
path working; working._str.resize(0);
|
||||||
@@ -253,16 +280,83 @@ public:
|
|||||||
|
|
||||||
// Iterator ============================================================================================================
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns an iterator at the first filename in the path
|
||||||
iterator begin() const {
|
iterator begin() const {
|
||||||
return iterator(this, 0);
|
return iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
|
/// \returns an iterator to the end of the path
|
||||||
iterator end() const {
|
iterator end() const {
|
||||||
return iterator(this, _str.size());
|
return iterator(this, _str.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `iterator`
|
||||||
class iterator {
|
class iterator {
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief copy constructor
|
||||||
|
/// \param it the iterator to copy
|
||||||
|
constexpr iterator(const iterator& it) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief move constructor
|
||||||
|
/// \param it the iterator to move
|
||||||
|
constexpr iterator(iterator&& it) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief dereference operator
|
||||||
|
/// \returns copy of the current file in the path
|
||||||
|
constexpr string operator*() const {
|
||||||
|
if ((*_str)[_pos] == '/') {
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t e = _str->find('/', _pos);
|
||||||
|
return _str->substring(_pos, e - _pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief prefix increment operator
|
||||||
|
/// \returns \f$self\f$ after having moved to the next element in the list
|
||||||
|
constexpr iterator& operator++() {
|
||||||
|
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief postfix increment operator
|
||||||
|
/// \returns \f$self\f$ before having moved to the next element in the list
|
||||||
|
constexpr iterator operator++(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
this->operator++();
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator equality operator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||||
|
constexpr bool operator==(const iterator& rhs) const {
|
||||||
|
return _str == rhs._str and _pos == rhs._pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief iterator inequality operator
|
||||||
|
/// \param rhs the iterator to compare with
|
||||||
|
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||||
|
constexpr bool operator!=(const iterator& rhs) const {
|
||||||
|
return _str != rhs._str or _pos != rhs._pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const string* _str;
|
||||||
|
size_t _pos;
|
||||||
|
|
||||||
constexpr iterator(const path* path, size_t p)
|
constexpr iterator(const path* path, size_t p)
|
||||||
: _str(&path->_str)
|
: _str(&path->_str)
|
||||||
, _pos(p) {
|
, _pos(p) {
|
||||||
@@ -289,40 +383,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator(const iterator&) = default;
|
friend struct path;
|
||||||
constexpr iterator(iterator&&) noexcept = default;
|
|
||||||
|
|
||||||
constexpr string operator*() const {
|
|
||||||
if ((*_str)[_pos] == '/') {
|
|
||||||
return string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t e = _str->find('/', _pos);
|
|
||||||
return _str->substring(_pos, e - _pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr iterator& operator++() {
|
|
||||||
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr iterator operator++(int) {
|
|
||||||
iterator it = *this;
|
|
||||||
this->operator++();
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const iterator& rhs) const {
|
|
||||||
return _str == rhs._str and _pos == rhs._pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const iterator& rhs) const {
|
|
||||||
return _str != rhs._str or _pos != rhs._pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const string* _str;
|
|
||||||
size_t _pos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -34,31 +34,165 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, char x, int base);
|
char* to_chars(char* first, char* last, char x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed char x, int base);
|
char* to_chars(char* first, char* last, signed char x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned char x, int base);
|
char* to_chars(char* first, char* last, unsigned char x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed short x, int base);
|
char* to_chars(char* first, char* last, signed short x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned short x, int base);
|
char* to_chars(char* first, char* last, unsigned short x, int base);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed int x, int base);
|
char* to_chars(char* first, char* last, signed int x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned int x, int base);
|
char* to_chars(char* first, char* last, unsigned int x, int base);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed long x, int base);
|
char* to_chars(char* first, char* last, signed long x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned long x, int base);
|
char* to_chars(char* first, char* last, unsigned long x, int base);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed long long x, int base);
|
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, signed long long x, int base);
|
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief integer to ascii
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param base the base to interpret the integer as
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, float x);
|
char* to_chars(char* first, char* last, float x);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param fmt the float string format to use
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, float x, char fmt);
|
char* to_chars(char* first, char* last, float x, char fmt);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief float to ascii
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param fmt the float string format to use
|
||||||
|
/// \param precision the number of decimal places to write
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, float x, char fmt, int precision);
|
char* to_chars(char* first, char* last, float x, char fmt, int precision);
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, double x);
|
char* to_chars(char* first, char* last, double x);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param fmt the float string format to use
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, double x, char fmt);
|
char* to_chars(char* first, char* last, double x, char fmt);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief float to ascii
|
||||||
|
/// \param first the start of the buffer
|
||||||
|
/// \param last the end of the buffer
|
||||||
|
/// \param x the value to write
|
||||||
|
/// \param fmt the float string format to use
|
||||||
|
/// \param precision the number of decimal places to write
|
||||||
|
/// \returns a pointer to one past the last written character
|
||||||
char* to_chars(char* first, char* last, double x, char fmt, int precision);
|
char* to_chars(char* first, char* last, double x, char fmt, int precision);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,12 @@
|
|||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
///
|
||||||
|
/// \brief C++ 20 format specification
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param str The format string
|
||||||
|
/// \param args The argument values
|
||||||
|
/// \returns A formatted string using the C++20 format specification
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
string format(const cstring& str, ArgsT&&...args) {
|
string format(const cstring& str, ArgsT&&...args) {
|
||||||
static constexpr size_t argc = sizeof...(ArgsT);
|
static constexpr size_t argc = sizeof...(ArgsT);
|
||||||
|
|||||||
@@ -35,14 +35,18 @@
|
|||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
///
|
||||||
|
/// \brief helper struct for `fennec::format`
|
||||||
struct format_arg {
|
struct format_arg {
|
||||||
char fill;
|
char fill; //!< the fill character of the argument
|
||||||
char align, sign;
|
char align; //!< the alignment of the argument
|
||||||
bool alt, upper;
|
char sign; //!< the sign to use
|
||||||
size_t width, precision;
|
bool alt; //!< alternate form
|
||||||
size_t base;
|
bool upper; //!< print as uppercase
|
||||||
char type;
|
size_t width; //!< the width of the fill
|
||||||
|
size_t precision; //!< the number of decimal points
|
||||||
|
size_t base; //!< the base to use
|
||||||
|
char type; //!< the argument type
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ namespace fennec
|
|||||||
/// \tparam T The type to format
|
/// \tparam T The type to format
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct formatter {
|
struct formatter {
|
||||||
|
///
|
||||||
|
/// \brief default format function
|
||||||
|
///
|
||||||
|
/// \details throws a static assertion
|
||||||
|
/// \returns empty string
|
||||||
string operator()(const format_arg&, const T&) {
|
string operator()(const format_arg&, const T&) {
|
||||||
static_assert(false, "Formatter not implemented for the provided type.");
|
static_assert(false, "Formatter not implemented for the provided type.");
|
||||||
return string("");
|
return string("");
|
||||||
@@ -54,29 +59,55 @@ struct formatter {
|
|||||||
|
|
||||||
// strings =============================================================================================================
|
// strings =============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of a character array
|
||||||
|
/// \tparam N the number of characters
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct formatter<char[N]> {
|
struct formatter<char[N]> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param str the string argument
|
||||||
|
/// \returns the formatted version of \f$str\f$
|
||||||
string operator()(const format_arg&, const char (&str)[N]) {
|
string operator()(const format_arg&, const char (&str)[N]) {
|
||||||
return string(str);
|
return string(str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of a character array
|
||||||
|
/// \tparam N the number of characters
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
struct formatter<const char[N]> {
|
struct formatter<const char[N]> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param str the string argument
|
||||||
|
/// \returns the formatted version of \f$str\f$
|
||||||
string operator()(const format_arg&, const char (&str)[N]) {
|
string operator()(const format_arg&, const char (&str)[N]) {
|
||||||
return string(str);
|
return string(str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of a C-Style string
|
||||||
template<>
|
template<>
|
||||||
struct formatter<cstring> {
|
struct formatter<cstring> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param str the string argument
|
||||||
|
/// \returns the formatted version of \f$str\f$
|
||||||
string operator()(const format_arg&, const cstring& str) {
|
string operator()(const format_arg&, const cstring& str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of a string
|
||||||
template<>
|
template<>
|
||||||
struct formatter<string> {
|
struct formatter<string> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param str the string argument
|
||||||
|
/// \returns the formatted version of \f$str\f$
|
||||||
string operator()(const format_arg&, const string& str) {
|
string operator()(const format_arg&, const string& str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -85,8 +116,15 @@ struct formatter<string> {
|
|||||||
|
|
||||||
// decimal types =======================================================================================================
|
// decimal types =======================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of integral types
|
||||||
template<typename IntT> requires(is_integral_v<IntT> and not is_bool_v<IntT>)
|
template<typename IntT> requires(is_integral_v<IntT> and not is_bool_v<IntT>)
|
||||||
struct formatter<IntT> {
|
struct formatter<IntT> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param fmt the format specification
|
||||||
|
/// \param x the integral argument
|
||||||
|
/// \returns the formatted version of \f$x\f$
|
||||||
string operator()(const format_arg& fmt, IntT x) {
|
string operator()(const format_arg& fmt, IntT x) {
|
||||||
char digits[128] = {};
|
char digits[128] = {};
|
||||||
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.base);
|
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.base);
|
||||||
@@ -154,8 +192,15 @@ struct formatter<IntT> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of boolean types
|
||||||
template<typename BoolT> requires(is_bool_v<BoolT>)
|
template<typename BoolT> requires(is_bool_v<BoolT>)
|
||||||
struct formatter<BoolT> {
|
struct formatter<BoolT> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param fmt the format specification
|
||||||
|
/// \param x the boolean argument
|
||||||
|
/// \returns the formatted version of \f$x\f$
|
||||||
string operator()(const format_arg& fmt, BoolT x) {
|
string operator()(const format_arg& fmt, BoolT x) {
|
||||||
if (fmt.type == 's' or fmt.type == '\0') {
|
if (fmt.type == 's' or fmt.type == '\0') {
|
||||||
return x ? string("true") : string("false");
|
return x ? string("true") : string("false");
|
||||||
@@ -165,8 +210,15 @@ struct formatter<BoolT> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief formatter of floating point types
|
||||||
template<typename FloatT> requires(is_floating_point_v<FloatT>)
|
template<typename FloatT> requires(is_floating_point_v<FloatT>)
|
||||||
struct formatter<FloatT> {
|
struct formatter<FloatT> {
|
||||||
|
///
|
||||||
|
/// \brief format function
|
||||||
|
/// \param fmt the format specification
|
||||||
|
/// \param x the float argument
|
||||||
|
/// \returns the formatted version of \f$x\f$
|
||||||
string operator()(const format_arg& fmt, FloatT x) {
|
string operator()(const format_arg& fmt, FloatT x) {
|
||||||
|
|
||||||
// nan & inf cases
|
// nan & inf cases
|
||||||
|
|||||||
@@ -46,18 +46,18 @@
|
|||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// assert(expr, desc)
|
/// assert(expr, desc)
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Make an assertion with expression `expr` and provide a description `desc`. Only halts in debug mode.
|
/// Make an assertion with expression \f$expr\f$ and provide a description \f$desc\f$. Only halts in debug mode.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// assertf(expr, desc)
|
/// assertf(expr, desc)
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Make an assertion with expression `expr` and provide a description `desc`. Always halts.
|
/// Make an assertion with expression \f$expr\f$ and provide a description \f$desc\f$. Always halts.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// assertd(expr, desc)
|
/// assertd(expr, desc)
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Make an assertion, ***only in debug mode***, with expression `expr` and provide a description `desc`.
|
/// Make an assertion, ***only in debug mode***, with expression \f$expr\f$ and provide a description \f$desc\f$.
|
||||||
/// This should be used when the branching caused by `assert` would hinder performance in release mode.
|
/// This should be used when the branching caused by \f$assert\f$ would hinder performance in release mode.
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -90,12 +90,12 @@ using conditional_t
|
|||||||
= typename conditional<B, TrueT, FalseT>::type;
|
= typename conditional<B, TrueT, FalseT>::type;
|
||||||
|
|
||||||
|
|
||||||
// specialization of fennec::conditional for `true` case
|
// specialization of fennec::conditional for \f$true\f$ case
|
||||||
template<typename T, typename F>
|
template<typename T, typename F>
|
||||||
struct conditional<true, T, F> : type_identity<T>{};
|
struct conditional<true, T, F> : type_identity<T>{};
|
||||||
|
|
||||||
|
|
||||||
// specialization of fennec::conditional for `false` case
|
// specialization of fennec::conditional for \f$false\f$ case
|
||||||
template<typename T, typename F>
|
template<typename T, typename F>
|
||||||
struct conditional<false, T, F> : type_identity<F>{};
|
struct conditional<false, T, F> : type_identity<F>{};
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ struct conditional<false, T, F> : type_identity<F>{};
|
|||||||
///
|
///
|
||||||
/// \brief Detect whether `DetectT<ArgsT...>` is a valid type
|
/// \brief Detect whether `DetectT<ArgsT...>` is a valid type
|
||||||
///
|
///
|
||||||
/// \details Selects `DetectT<ArgsT...>` if it exists, otherwise selects `DefaultT` The chosen type is stored in `detect::type` and
|
/// \details Selects `DetectT<ArgsT...>` if it exists, otherwise selects \f$DefaultT\f$ The chosen type is stored in `detect::type` and
|
||||||
/// a boolean value is stored in `detect::is_detected` representing whether `DetectT<ArgsT...>` is found.
|
/// a boolean value is stored in `detect::is_detected` representing whether `DetectT<ArgsT...>` is found.
|
||||||
/// \tparam DefaultT Default type
|
/// \tparam DefaultT Default type
|
||||||
/// \tparam DetectT Type to detect
|
/// \tparam DetectT Type to detect
|
||||||
@@ -138,7 +138,7 @@ struct detect<DefaultT, DetectT, ArgsT...>
|
|||||||
///
|
///
|
||||||
/// \brief Leverage SFINAE to conditionally enable a function or class at compile-time
|
/// \brief Leverage SFINAE to conditionally enable a function or class at compile-time
|
||||||
///
|
///
|
||||||
/// \details If `B` is `true`, define a public member type `type`. Otherwise, there is no member. <br>
|
/// \details If \f$B\f$ is \f$true\f$, define a public member type \f$type\f$. Otherwise, there is no member. <br>
|
||||||
/// **Example Usage**
|
/// **Example Usage**
|
||||||
/// \code{.cpp}
|
/// \code{.cpp}
|
||||||
/// template<typename TypeT,
|
/// template<typename TypeT,
|
||||||
|
|||||||
@@ -55,44 +55,44 @@
|
|||||||
/// `FENNEC_HAS_BUILTIN_IS_CONVERTIBLE` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_CONVERTIBLE` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)`
|
/// `B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if type `X` can be converted to type `Y`.
|
/// Checks if type \f$X\f$ can be converted to type \f$Y\f$.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_EMPTY` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_EMPTY` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_EMPTY(X)`
|
/// `B FENNEC_BUILTIN_IS_EMPTY(X)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if type `X` stores no data.
|
/// Checks if type \f$X\f$ stores no data.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_POLYMORPHIC` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_POLYMORPHIC` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_POLYMORPHIC(X)`
|
/// `B FENNEC_BUILTIN_IS_POLYMORPHIC(X)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if type `X` is polymorphic, this is for classes only thus checks only for subtyping
|
/// Checks if type \f$X\f$ is polymorphic, this is for classes only thus checks only for subtyping
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_FINAL` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_FINAL` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_FINAL(X)`
|
/// `B FENNEC_BUILTIN_IS_FINAL(X)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if type `X` is final, meaning a function or class cannot be derived from.
|
/// Checks if type \f$X\f$ is final, meaning a function or class cannot be derived from.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_ABSTRACT` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_ABSTRACT` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_ABSTRACT(X)`
|
/// `B FENNEC_BUILTIN_IS_ABSTRACT(X)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Opposite of `FENNEC_BUILTIN_IS_FINAL`, checks if abstract, meaning `X` has at least one pure virtual function.
|
/// Opposite of `FENNEC_BUILTIN_IS_FINAL`, checks if abstract, meaning \f$X\f$ has at least one pure virtual function.
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)`
|
/// `B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if `X` has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
|
/// Checks if \f$X\f$ has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
|
||||||
/// for this trait
|
/// for this trait
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// `FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE` <br>
|
/// `FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE` <br>
|
||||||
/// `B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)`
|
/// `B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)`
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// Checks if type `X` is constructible with args `...`, such that `X::X(...)` exists.
|
/// Checks if type \f$X\f$ is constructible with args `...`, such that `X::X(...)` exists.
|
||||||
///
|
///
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// \brief metaprogramming sequence
|
/// \brief metaprogramming sequence
|
||||||
///
|
///
|
||||||
/// \details Stores a sequence of values of type `ValueT` as a template pack.
|
/// \details Stores a sequence of values of type \f$ValueT\f$ as a template pack.
|
||||||
/// You can access the parameter pack in another template function, i.e.
|
/// You can access the parameter pack in another template function, i.e.
|
||||||
/// \code{cpp}
|
/// \code{cpp}
|
||||||
/// template<typename TypeT, TypeT...Values>
|
/// template<typename TypeT, TypeT...Values>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ template<size_t n, typename...TypesT> using nth_element_t = nth_element<n, Types
|
|||||||
// fennec::replace_first_element =======================================================================================
|
// fennec::replace_first_element =======================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first \f$ArgT\f$ of `ArgsT...` with \f$SubT\f$
|
||||||
template<typename ClassT, typename SubT> struct replace_first_element { };
|
template<typename ClassT, typename SubT> struct replace_first_element { };
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
@@ -127,7 +127,7 @@ template<typename...Ts> constexpr size_t max_element_size_v = max_element_size<T
|
|||||||
// fennec::find_element ================================================================================================
|
// fennec::find_element ================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of `T` in `Ts`, if `T` is not found, results in `sizeof...(Ts)`
|
/// \brief Finds the index of \f$T\f$ in \f$Ts\f$, if \f$T\f$ is not found, results in `sizeof...(Ts)`
|
||||||
/// \tparam T The type to find
|
/// \tparam T The type to find
|
||||||
/// \tparam Ts The type sequence to check
|
/// \tparam Ts The type sequence to check
|
||||||
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
|
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
|
||||||
@@ -169,7 +169,7 @@ struct search_element_args<SearchT, type_sequence<ArgsT...>, TypesT...>
|
|||||||
// fennec::contains_element ============================================================================================
|
// fennec::contains_element ============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Checks if the type sequence `Ts...` contains `T`
|
/// \brief Checks if the type sequence `Ts...` contains \f$T\f$
|
||||||
/// \tparam T The type to find
|
/// \tparam T The type to find
|
||||||
/// \tparam Ts The type sequence to check
|
/// \tparam Ts The type sequence to check
|
||||||
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
|
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a floating point type
|
/// \brief Check if \p T is of a floating point type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a floating point type and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_lvalue_reference
|
template<typename T> struct is_lvalue_reference
|
||||||
: detail::_is_lvalue_reference<T>{};
|
: detail::_is_lvalue_reference<T>{};
|
||||||
@@ -666,7 +666,7 @@ template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_referenc
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a floating point type
|
/// \brief Check if \p T is of a floating point type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a floating point type and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_rvalue_reference
|
template<typename T> struct is_rvalue_reference
|
||||||
: detail::_is_rvalue_reference<T>{};
|
: detail::_is_rvalue_reference<T>{};
|
||||||
@@ -683,7 +683,7 @@ template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_referenc
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is a pointer to a member function
|
/// \brief Check if \p T is a pointer to a member function
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is pointer to a member function and store it in `is_member_function_pointer::value`.
|
/// \details Checks if type \f$T\f$ is pointer to a member function and store it in `is_member_function_pointer::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_member_function_pointer
|
template<typename T> struct is_member_function_pointer
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(T)> {};
|
||||||
@@ -700,7 +700,7 @@ template<typename T> constexpr bool_t is_member_function_pointer_v = is_member_f
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is a pointer to a member object
|
/// \brief Check if \p T is a pointer to a member object
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is pointer to a member object and store it in `is_member_object_pointer::value`.
|
/// \details Checks if type \f$T\f$ is pointer to a member object and store it in `is_member_object_pointer::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_member_object_pointer
|
template<typename T> struct is_member_object_pointer
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(T)> {};
|
||||||
@@ -722,7 +722,7 @@ template<typename T> constexpr bool_t is_member_object_pointer_v = is_member_obj
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is an arithmetic type
|
/// \brief Check if \p T is an arithmetic type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_arithmetic
|
template<typename T> struct is_arithmetic
|
||||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||||
@@ -753,7 +753,7 @@ template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::valu
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is an arithmetic type
|
/// \brief Check if \p T is an arithmetic type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_scalar::value`.
|
/// \details Checks if type \f$T\f$ is a built-in type with arithmetic operators and store it in `is_scalar::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_scalar
|
template<typename T> struct is_scalar
|
||||||
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
||||||
@@ -770,7 +770,7 @@ template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is an object
|
/// \brief Check if \p T is an object
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is an object and store it in `is_object::value`.
|
/// \details Checks if type \f$T\f$ is an object and store it in `is_object::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_object : bool_constant<FENNEC_BUILTIN_IS_OBJECT(T)> {};
|
template<typename T> struct is_object : bool_constant<FENNEC_BUILTIN_IS_OBJECT(T)> {};
|
||||||
|
|
||||||
@@ -786,7 +786,7 @@ template<typename T> constexpr bool_t is_object_v = is_object<T>::value;
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is a object compound type
|
/// \brief Check if \p T is a object compound type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is an object and store it in `is_compound::value`.
|
/// \details Checks if type \f$T\f$ is an object and store it in `is_compound::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_compound : bool_constant<not is_fundamental_v<T>> {};
|
template<typename T> struct is_compound : bool_constant<not is_fundamental_v<T>> {};
|
||||||
|
|
||||||
@@ -802,7 +802,7 @@ template<typename T> constexpr bool_t is_compound_v = is_compound<T>::value;
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a reference type
|
/// \brief Check if \p T is of a reference type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a reference type and store it in `is_reference::value`.
|
/// \details Checks if type \f$T\f$ is a reference type and store it in `is_reference::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_reference
|
template<typename T> struct is_reference
|
||||||
: detail::_is_reference<T>{};
|
: detail::_is_reference<T>{};
|
||||||
@@ -819,7 +819,7 @@ template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is a pointer to a member
|
/// \brief Check if \p T is a pointer to a member
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is pointer to a member and store it in `is_member_function_pointer::value`.
|
/// \details Checks if type \f$T\f$ is pointer to a member and store it in `is_member_function_pointer::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_member_pointer
|
template<typename T> struct is_member_pointer
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_POINTER(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_POINTER(T)> {};
|
||||||
@@ -841,7 +841,7 @@ template<typename T> constexpr bool_t is_member_pointer_v = is_member_pointer<T>
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a const type
|
/// \brief Check if \p T is of a const type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a const type and store it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a const type and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_const
|
template<typename T> struct is_const
|
||||||
: detail::_is_const<T>{};
|
: detail::_is_const<T>{};
|
||||||
@@ -858,7 +858,7 @@ template<typename T> constexpr bool_t is_const_v = is_const<T> {};
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a volatile type
|
/// \brief Check if \p T is of a volatile type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a volatile type and store it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a volatile type and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_volatile
|
template<typename T> struct is_volatile
|
||||||
: detail::_is_volatile<T>{};
|
: detail::_is_volatile<T>{};
|
||||||
@@ -873,9 +873,9 @@ template<typename T> constexpr bool_t is_volatile_v = is_volatile<T> {};
|
|||||||
// fennec::is_trivial --------------------------------------------------------------------------------------------------
|
// fennec::is_trivial --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is trivial
|
/// \brief Check if type \f$T\f$ is trivial
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_trivial : bool_constant<FENNEC_BUILTIN_IS_TRIVIAL(T)> {};
|
template<typename T> struct is_trivial : bool_constant<FENNEC_BUILTIN_IS_TRIVIAL(T)> {};
|
||||||
|
|
||||||
@@ -889,9 +889,9 @@ template<typename T> constexpr bool_t is_trivial_v = is_trivial<T>{};
|
|||||||
// fennec::is_trivially_copyable ---------------------------------------------------------------------------------------
|
// fennec::is_trivially_copyable ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is trivially_copyable
|
/// \brief Check if type \f$T\f$ is trivially_copyable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_trivially_copyable : bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(T)> {};
|
template<typename T> struct is_trivially_copyable : bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(T)> {};
|
||||||
|
|
||||||
@@ -905,9 +905,9 @@ template<typename T> constexpr bool_t is_trivially_copyable_v = is_trivially_cop
|
|||||||
// fennec::is_standard_layout ------------------------------------------------------------------------------------------
|
// fennec::is_standard_layout ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is standard_layout
|
/// \brief Check if type \f$T\f$ is standard_layout
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_standard_layout : bool_constant<FENNEC_BUILTIN_IS_STANDARD_LAYOUT(T)> {};
|
template<typename T> struct is_standard_layout : bool_constant<FENNEC_BUILTIN_IS_STANDARD_LAYOUT(T)> {};
|
||||||
|
|
||||||
@@ -921,9 +921,9 @@ template<typename T> constexpr bool_t is_standard_layout_v = is_standard_layout<
|
|||||||
// fennec::has_unique_object_representations ---------------------------------------------------------------------------
|
// fennec::has_unique_object_representations ---------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` has unique object representations
|
/// \brief Check if type \f$T\f$ has unique object representations
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct has_unique_object_representations
|
template<typename T> struct has_unique_object_representations
|
||||||
: bool_constant<FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(remove_cv_t<T>)> {};
|
: bool_constant<FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(remove_cv_t<T>)> {};
|
||||||
@@ -938,9 +938,9 @@ template<typename T> constexpr bool_t has_unique_object_representations_v = has_
|
|||||||
// fennec::is_empty ----------------------------------------------------------------------------------------------------
|
// fennec::is_empty ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is empty
|
/// \brief Check if type \f$T\f$ is empty
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_empty : bool_constant<FENNEC_BUILTIN_IS_EMPTY(T)> {};
|
template<typename T> struct is_empty : bool_constant<FENNEC_BUILTIN_IS_EMPTY(T)> {};
|
||||||
|
|
||||||
@@ -954,9 +954,9 @@ template<typename T> constexpr bool_t is_empty_v = is_empty<T>{};
|
|||||||
// fennec::is_polymorphic ----------------------------------------------------------------------------------------------
|
// fennec::is_polymorphic ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is polymorphic
|
/// \brief Check if type \f$T\f$ is polymorphic
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_polymorphic : bool_constant<FENNEC_BUILTIN_IS_POLYMORPHIC(T)> {};
|
template<typename T> struct is_polymorphic : bool_constant<FENNEC_BUILTIN_IS_POLYMORPHIC(T)> {};
|
||||||
|
|
||||||
@@ -970,9 +970,9 @@ template<typename T> constexpr bool_t is_polymorphic_v = is_polymorphic<T>{};
|
|||||||
// fennec::is_abstract -------------------------------------------------------------------------------------------------
|
// fennec::is_abstract -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is abstract
|
/// \brief Check if type \f$T\f$ is abstract
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_abstract : bool_constant<FENNEC_BUILTIN_IS_ABSTRACT(T)> {};
|
template<typename T> struct is_abstract : bool_constant<FENNEC_BUILTIN_IS_ABSTRACT(T)> {};
|
||||||
|
|
||||||
@@ -986,9 +986,9 @@ template<typename T> constexpr bool_t is_abstract_v = is_abstract<T>{};
|
|||||||
// fennec::is_complete -------------------------------------------------------------------------------------------------
|
// fennec::is_complete -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is complete
|
/// \brief Check if type \f$T\f$ is complete
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
||||||
|
|
||||||
@@ -1002,9 +1002,9 @@ template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
|||||||
// fennec::is_final -------------------------------------------------------------------------------------------------
|
// fennec::is_final -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is final
|
/// \brief Check if type \f$T\f$ is final
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_final : bool_constant<FENNEC_BUILTIN_IS_FINAL(T)> {};
|
template<typename T> struct is_final : bool_constant<FENNEC_BUILTIN_IS_FINAL(T)> {};
|
||||||
|
|
||||||
@@ -1018,9 +1018,9 @@ template<typename T> constexpr bool_t is_final_v = is_final<T>{};
|
|||||||
// fennec::is_aggregate -------------------------------------------------------------------------------------------------
|
// fennec::is_aggregate -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is aggregate
|
/// \brief Check if type \f$T\f$ is aggregate
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_aggregate : bool_constant<FENNEC_BUILTIN_IS_AGGREGATE(T)> {};
|
template<typename T> struct is_aggregate : bool_constant<FENNEC_BUILTIN_IS_AGGREGATE(T)> {};
|
||||||
|
|
||||||
@@ -1037,7 +1037,7 @@ template<typename T> constexpr bool_t is_aggregate_v = is_aggregate<T>{};
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of a signed integral
|
/// \brief Check if \p T is of a signed integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_signed
|
template<typename T> struct is_signed
|
||||||
: detail::_is_signed<remove_cvref_t<T>> {};
|
: detail::_is_signed<remove_cvref_t<T>> {};
|
||||||
@@ -1055,7 +1055,7 @@ template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
|||||||
///
|
///
|
||||||
/// \brief Check if \p T is of an unsigned integral
|
/// \brief Check if \p T is of an unsigned integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type \f$T\f$ is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_unsigned
|
template<typename T> struct is_unsigned
|
||||||
: detail::_is_unsigned<remove_cvref_t<T>> {};
|
: detail::_is_unsigned<remove_cvref_t<T>> {};
|
||||||
@@ -1172,9 +1172,9 @@ template<typename T> constexpr bool_t is_scoped_enum_v = is_scoped_enum<T>::valu
|
|||||||
// fennec::is_convertible ----------------------------------------------------------------------------------------------
|
// fennec::is_convertible ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T0` can be converted `T1`
|
/// \brief Check if type \f$T0\f$ can be converted \f$T1\f$
|
||||||
///
|
///
|
||||||
/// \details Checks if `TypeT0`
|
/// \details Checks if \f$TypeT0\f$
|
||||||
/// \tparam FromT First type
|
/// \tparam FromT First type
|
||||||
/// \tparam ToT Second type
|
/// \tparam ToT Second type
|
||||||
template<typename FromT, typename ToT> struct is_convertible
|
template<typename FromT, typename ToT> struct is_convertible
|
||||||
@@ -1191,8 +1191,8 @@ template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_co
|
|||||||
// fennec::is_constructible --------------------------------------------------------------------------------------------
|
// fennec::is_constructible --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
|
/// \brief Check if \f$ClassT\f$ can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
|
||||||
/// This may be read as "is `ClassT` constructible with `ArgsT`"
|
/// This may be read as "is \f$ClassT\f$ constructible with \f$ArgsT\f$"
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
/// \tparam ArgsT The arguments for the specific constructor
|
/// \tparam ArgsT The arguments for the specific constructor
|
||||||
template<typename ClassT, typename...ArgsT> struct is_constructible
|
template<typename ClassT, typename...ArgsT> struct is_constructible
|
||||||
@@ -1207,7 +1207,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v
|
|||||||
// fennec::is_trivially_constructible ----------------------------------------------------------------------------------
|
// fennec::is_trivially_constructible ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially constructible
|
/// \brief Check if \f$ClassT\f$ is trivially constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
/// \tparam ArgsT The arguments for the specific constructor
|
/// \tparam ArgsT The arguments for the specific constructor
|
||||||
template<typename ClassT, typename...ArgsT> struct is_trivially_constructible
|
template<typename ClassT, typename...ArgsT> struct is_trivially_constructible
|
||||||
@@ -1222,7 +1222,7 @@ template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_tri
|
|||||||
// fennec::is_nothrow_constructible ------------------------------------------------------------------------------------
|
// fennec::is_nothrow_constructible ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow constructible
|
/// \brief Check if \f$ClassT\f$ is nothrow constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
/// \tparam ArgsT The arguments for the specific constructor
|
/// \tparam ArgsT The arguments for the specific constructor
|
||||||
template<typename ClassT, typename...ArgsT> struct is_nothrow_constructible
|
template<typename ClassT, typename...ArgsT> struct is_nothrow_constructible
|
||||||
@@ -1237,7 +1237,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_constructible_v = is_nothr
|
|||||||
// fennec::is_default_constructible ------------------------------------------------------------------------------------
|
// fennec::is_default_constructible ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is default constructible
|
/// \brief Check if \f$ClassT\f$ is default constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_default_constructible
|
template<typename ClassT> struct is_default_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT)> {};
|
||||||
@@ -1251,7 +1251,7 @@ template<typename ClassT> constexpr bool_t is_default_constructible_v = is_defau
|
|||||||
// fennec::is_trivially_default_constructible --------------------------------------------------------------------------
|
// fennec::is_trivially_default_constructible --------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially default constructible
|
/// \brief Check if \f$ClassT\f$ is trivially default constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_default_constructible
|
template<typename ClassT> struct is_trivially_default_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
|
||||||
@@ -1265,7 +1265,7 @@ template<typename ClassT> constexpr bool_t is_trivially_default_constructible_v
|
|||||||
// fennec::is_nothrow_default_constructible --------------------------------------------------------------------------
|
// fennec::is_nothrow_default_constructible --------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow default constructible
|
/// \brief Check if \f$ClassT\f$ is nothrow default constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_default_constructible
|
template<typename ClassT> struct is_nothrow_default_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE(ClassT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE(ClassT)> {};
|
||||||
@@ -1279,7 +1279,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_default_constructible_v =
|
|||||||
// fennec::is_copy_constructible ---------------------------------------------------------------------------------------
|
// fennec::is_copy_constructible ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is copy constructible
|
/// \brief Check if \f$ClassT\f$ is copy constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_copy_constructible
|
template<typename ClassT> struct is_copy_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1293,7 +1293,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructib
|
|||||||
// fennec::is_trivially_copy_constructible -----------------------------------------------------------------------------
|
// fennec::is_trivially_copy_constructible -----------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially copy constructible
|
/// \brief Check if \f$ClassT\f$ is trivially copy constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_copy_constructible
|
template<typename ClassT> struct is_trivially_copy_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1307,7 +1307,7 @@ template<typename ClassT> struct is_trivially_copy_constructible
|
|||||||
// fennec::is_nothrow_copy_constructible -------------------------------------------------------------------------------
|
// fennec::is_nothrow_copy_constructible -------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow copy constructible
|
/// \brief Check if \f$ClassT\f$ is nothrow copy constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_copy_constructible
|
template<typename ClassT> struct is_nothrow_copy_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1321,7 +1321,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_nothrow_copy_con
|
|||||||
// fennec::is_move_constructible ---------------------------------------------------------------------------------------
|
// fennec::is_move_constructible ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is move constructible
|
/// \brief Check if \f$ClassT\f$ is move constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_move_constructible
|
template<typename ClassT> struct is_move_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
||||||
@@ -1335,7 +1335,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructib
|
|||||||
// fennec::is_trivially_move_constructible -----------------------------------------------------------------------------
|
// fennec::is_trivially_move_constructible -----------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially move constructible
|
/// \brief Check if \f$ClassT\f$ is trivially move constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_move_constructible
|
template<typename ClassT> struct is_trivially_move_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1349,7 +1349,7 @@ template<typename ClassT> struct is_trivially_move_constructible
|
|||||||
// fennec::is_nothrow_move_constructible -------------------------------------------------------------------------------
|
// fennec::is_nothrow_move_constructible -------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow move constructible
|
/// \brief Check if \f$ClassT\f$ is nothrow move constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_move_constructible
|
template<typename ClassT> struct is_nothrow_move_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1363,7 +1363,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_nothrow_move_con
|
|||||||
// fennec::is_assignable -----------------------------------------------------------------------------------------------
|
// fennec::is_assignable -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is assignable
|
/// \brief Check if \f$ClassT\f$ is assignable
|
||||||
/// \tparam ClassAT The class type to test
|
/// \tparam ClassAT The class type to test
|
||||||
/// \tparam ClassBT The arguments for the specific constructor
|
/// \tparam ClassBT The arguments for the specific constructor
|
||||||
template<typename ClassAT, typename ClassBT> struct is_assignable
|
template<typename ClassAT, typename ClassBT> struct is_assignable
|
||||||
@@ -1378,7 +1378,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_assignable_v =
|
|||||||
// fennec::is_trivially_assignable -------------------------------------------------------------------------------------
|
// fennec::is_trivially_assignable -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially assignable
|
/// \brief Check if \f$ClassT\f$ is trivially assignable
|
||||||
/// \tparam ClassAT The class type to test
|
/// \tparam ClassAT The class type to test
|
||||||
/// \tparam ClassBT The arguments for the specific constructor
|
/// \tparam ClassBT The arguments for the specific constructor
|
||||||
template<typename ClassAT, typename ClassBT> struct is_trivially_assignable
|
template<typename ClassAT, typename ClassBT> struct is_trivially_assignable
|
||||||
@@ -1394,7 +1394,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_trivially_assig
|
|||||||
// fennec::is_nothrow_assignable ---------------------------------------------------------------------------------------
|
// fennec::is_nothrow_assignable ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow assignable
|
/// \brief Check if \f$ClassT\f$ is nothrow assignable
|
||||||
/// \tparam ClassAT The class type to test
|
/// \tparam ClassAT The class type to test
|
||||||
/// \tparam ClassBT The arguments for the specific constructor
|
/// \tparam ClassBT The arguments for the specific constructor
|
||||||
template<typename ClassAT, typename ClassBT> struct is_nothrow_assignable
|
template<typename ClassAT, typename ClassBT> struct is_nothrow_assignable
|
||||||
@@ -1409,7 +1409,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_nothrow_assigna
|
|||||||
// fennec::is_copy_assignable ------------------------------------------------------------------------------------------
|
// fennec::is_copy_assignable ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is copy assignable
|
/// \brief Check if \f$ClassT\f$ is copy assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_copy_assignable
|
template<typename ClassT> struct is_copy_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1423,7 +1423,7 @@ template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assign
|
|||||||
// fennec::is_trivially_copy_assignable --------------------------------------------------------------------------------
|
// fennec::is_trivially_copy_assignable --------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially_copy assignable
|
/// \brief Check if \f$ClassT\f$ is trivially_copy assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_copy_assignable
|
template<typename ClassT> struct is_trivially_copy_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1437,7 +1437,7 @@ template<typename ClassT> constexpr bool_t is_trivially_copy_assignable_v = is_t
|
|||||||
// fennec::is_nothrow_copy_assignable ----------------------------------------------------------------------------------
|
// fennec::is_nothrow_copy_assignable ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow_copy assignable
|
/// \brief Check if \f$ClassT\f$ is nothrow_copy assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_copy_assignable
|
template<typename ClassT> struct is_nothrow_copy_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||||
@@ -1451,7 +1451,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_copy_assignable_v = is_not
|
|||||||
// fennec::is_move_assignable ------------------------------------------------------------------------------------------
|
// fennec::is_move_assignable ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is move assignable
|
/// \brief Check if \f$ClassT\f$ is move assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_move_assignable
|
template<typename ClassT> struct is_move_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||||
@@ -1465,7 +1465,7 @@ template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assign
|
|||||||
// fennec::is_trivially_move_assignable --------------------------------------------------------------------------------
|
// fennec::is_trivially_move_assignable --------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially_move assignable
|
/// \brief Check if \f$ClassT\f$ is trivially_move assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_move_assignable
|
template<typename ClassT> struct is_trivially_move_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||||
@@ -1479,7 +1479,7 @@ template<typename ClassT> constexpr bool_t is_trivially_move_assignable_v = is_t
|
|||||||
// fennec::is_nothrow_move_assignable --------------------------------------------------------------------------------
|
// fennec::is_nothrow_move_assignable --------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow_move assignable
|
/// \brief Check if \f$ClassT\f$ is nothrow_move assignable
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_move_assignable
|
template<typename ClassT> struct is_nothrow_move_assignable
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||||
@@ -1493,7 +1493,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_move_assignable_v = is_not
|
|||||||
// fennec::is_destructible ---------------------------------------------------------------------------------------------
|
// fennec::is_destructible ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is destructible
|
/// \brief Check if \f$ClassT\f$ is destructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_destructible
|
template<typename ClassT> struct is_destructible
|
||||||
: detail::_is_destructible<ClassT>::type {};
|
: detail::_is_destructible<ClassT>::type {};
|
||||||
@@ -1507,7 +1507,7 @@ template<typename ClassT> constexpr bool_t is_destructible_v = is_destructible<C
|
|||||||
// fennec::is_trivially_destructible -----------------------------------------------------------------------------------
|
// fennec::is_trivially_destructible -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially destructible
|
/// \brief Check if \f$ClassT\f$ is trivially destructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_trivially_destructible
|
template<typename ClassT> struct is_trivially_destructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
||||||
@@ -1521,7 +1521,7 @@ template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_triv
|
|||||||
// fennec::is_nothrow_destructible -------------------------------------------------------------------------------------
|
// fennec::is_nothrow_destructible -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is nothrow destructible
|
/// \brief Check if \f$ClassT\f$ is nothrow destructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_nothrow_destructible
|
template<typename ClassT> struct is_nothrow_destructible
|
||||||
: detail::_is_nothrow_destructible<ClassT>::type {};
|
: detail::_is_nothrow_destructible<ClassT>::type {};
|
||||||
@@ -1542,7 +1542,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_destructible_v = is_nothro
|
|||||||
///
|
///
|
||||||
/// \brief Check if the two types are identical
|
/// \brief Check if the two types are identical
|
||||||
///
|
///
|
||||||
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
/// \details Checks if \f$T0\f$ and \f$T1\f$ are identical and store it in `is_same::value`
|
||||||
/// \tparam T0 first type to check
|
/// \tparam T0 first type to check
|
||||||
/// \tparam T1 second type to check
|
/// \tparam T1 second type to check
|
||||||
template<typename T0, typename T1> struct is_same : false_type {};
|
template<typename T0, typename T1> struct is_same : false_type {};
|
||||||
@@ -1561,9 +1561,9 @@ template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1>
|
|||||||
// fennec::is_base_of --------------------------------------------------------------------------------------------------
|
// fennec::is_base_of --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `Derived` has a base type of `Base`
|
/// \brief Check if \f$Derived\f$ has a base type of \f$Base\f$
|
||||||
///
|
///
|
||||||
/// \details Checks if `Base` is a base type of `Derived` and stores it in `is_base_of::value`
|
/// \details Checks if \f$Base\f$ is a base type of \f$Derived\f$ and stores it in `is_base_of::value`
|
||||||
/// \tparam Base base type to check
|
/// \tparam Base base type to check
|
||||||
/// \tparam Derived derived type to check
|
/// \tparam Derived derived type to check
|
||||||
template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
||||||
@@ -1581,9 +1581,9 @@ template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_bas
|
|||||||
// fennec::is_iterable -------------------------------------------------------------------------------------------------
|
// fennec::is_iterable -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is iterable
|
/// \brief Check if type \f$T\f$ is iterable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
||||||
|
|
||||||
@@ -1597,9 +1597,9 @@ template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
|||||||
// fennec::is_indexable ------------------------------------------------------------------------------------------------
|
// fennec::is_indexable ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is indexable
|
/// \brief Check if type \f$T\f$ is indexable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
||||||
|
|
||||||
@@ -1613,9 +1613,9 @@ template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
|||||||
// fennec::is_mappable -------------------------------------------------------------------------------------------------
|
// fennec::is_mappable -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if type `T` is mappable
|
/// \brief Check if type \f$T\f$ is mappable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if \f$T\f$
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ template<typename T> using decay_t = typename decay<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief adds a pointer level to \p T
|
/// \brief adds a pointer level to \p T
|
||||||
///
|
///
|
||||||
/// \details adds a pointer to the provided type such that `T` becomes `T*`
|
/// \details adds a pointer to the provided type such that \f$T\f$ becomes `T*`
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct add_pointer : detail::_add_pointer<T>{};
|
template<typename T> struct add_pointer : detail::_add_pointer<T>{};
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief removes a pointer level from \p T
|
/// \brief removes a pointer level from \p T
|
||||||
///
|
///
|
||||||
/// \details removes a pointer from the provided type such that `T*` becomes `T`
|
/// \details removes a pointer from the provided type such that `T*` becomes \f$T\f$
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};
|
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief removes all pointer levels from \p T
|
/// \brief removes all pointer levels from \p T
|
||||||
///
|
///
|
||||||
/// \details removes all pointers from the provided type such that `T*`, `T**`, etc. becomes `T`
|
/// \details removes all pointers from the provided type such that `T*`, `T**`, etc. becomes \f$T\f$
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct strip_pointers : conditional_t<
|
template<typename T> struct strip_pointers : conditional_t<
|
||||||
detail::_is_pointer<T>::value,
|
detail::_is_pointer<T>::value,
|
||||||
@@ -179,7 +179,7 @@ template<typename T> using strip_pointers_t = strip_pointers<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief add a reference to \p T
|
/// \brief add a reference to \p T
|
||||||
///
|
///
|
||||||
/// \details adds a pointer to the provided type such that `T` becomes `T&`
|
/// \details adds a pointer to the provided type such that \f$T\f$ becomes `T&`
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct add_reference : type_identity<T&> {};
|
template<typename T> struct add_reference : type_identity<T&> {};
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ template<typename T> using add_reference_t = typename add_reference<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief remove a reference from \p T
|
/// \brief remove a reference from \p T
|
||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `T&` and `T&&` become `T`
|
/// \details removes references from the provided type such that `T&` and `T&&` become \f$T\f$
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_reference : type_identity<T> {};
|
template<typename T> struct remove_reference : type_identity<T> {};
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ template<typename T> using add_rvalue_reference_t = typename add_rvalue_referen
|
|||||||
///
|
///
|
||||||
/// \brief add the const qualifier to the provided type \p T
|
/// \brief add the const qualifier to the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details adds const qualification to the provided type such that `T` becomes `const T`
|
/// \details adds const qualification to the provided type such that \f$T\f$ becomes `const T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_const : detail::_add_const<T> {};
|
template<typename T> struct add_const : detail::_add_const<T> {};
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ template<typename T> using add_const_t = typename add_const<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief remove the const qualifier from the provided type \p T
|
/// \brief remove the const qualifier from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes const qualification from the provided type such that `const T` becomes `T`
|
/// \details removes const qualification from the provided type such that `const T` becomes \f$T\f$
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_const : detail::_remove_const<T> {};
|
template<typename T> struct remove_const : detail::_remove_const<T> {};
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ template<typename T> using remove_const_t = typename remove_const<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief add the volatile qualifier to the provided type \p T
|
/// \brief add the volatile qualifier to the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `T` becomes `volatile T`
|
/// \details removes references from the provided type such that \f$T\f$ becomes `volatile T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_volatile : detail::_add_volatile<T> {};
|
template<typename T> struct add_volatile : detail::_add_volatile<T> {};
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ template<typename T> using add_volatile_t = typename add_volatile<T>::type;
|
|||||||
///
|
///
|
||||||
/// \brief remove the volatile qualifier from the provided type \p T
|
/// \brief remove the volatile qualifier from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `volatile T` becomes `T`
|
/// \details removes references from the provided type such that `volatile T` becomes \f$T\f$
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};
|
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ template<typename T> using remove_volatile_t = typename remove_volatile<T>::type
|
|||||||
///
|
///
|
||||||
/// \brief remove the volatile qualifier from the provided type \p T
|
/// \brief remove the volatile qualifier from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
|
/// \details removes references from the provided type such that \f$T\f$, `const T`, and `volatile T` become
|
||||||
/// `const volatile T`
|
/// `const volatile T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_cv : detail::_add_cv<T> {};
|
template<typename T> struct add_cv : detail::_add_cv<T> {};
|
||||||
@@ -301,7 +301,7 @@ template<typename T> using add_cv_t = typename add_cv<T>::type;
|
|||||||
/// \brief remove the const and volatile qualifiers from the provided type \p T
|
/// \brief remove the const and volatile qualifiers from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
|
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
|
||||||
/// `const volatile T` become `T`
|
/// `const volatile T` become \f$T\f$
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_cv : detail::_remove_cv<T> {};
|
template<typename T> struct remove_cv : detail::_remove_cv<T> {};
|
||||||
|
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ namespace fennec
|
|||||||
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
|
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
|
||||||
using intmax_t = intmax_t; ///< \brief Maximum Width Signed Integer Type
|
using intmax_t = intmax_t; ///< \brief Maximum Width Signed Integer Type
|
||||||
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type
|
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type
|
||||||
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
|
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By \f$sizeof\f$, `sizeof...`, and \f$alignof\f$
|
||||||
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
|
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
|
||||||
struct empty_t {};
|
struct empty_t {};
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ constexpr genType sqnorm(const qua<genType>& q) {
|
|||||||
///
|
///
|
||||||
/// \brief Norm Function
|
/// \brief Norm Function
|
||||||
/// \param q The Quaternion
|
/// \param q The Quaternion
|
||||||
/// \returns The Hamilton Tensor of `q`
|
/// \returns The Hamilton Tensor of \f$q\f$
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr genType norm(const qua<genType>& q) {
|
constexpr genType norm(const qua<genType>& q) {
|
||||||
return fennec::sqrt(sqnorm(q));
|
return fennec::sqrt(sqnorm(q));
|
||||||
@@ -61,7 +61,7 @@ constexpr genType norm(const qua<genType>& q) {
|
|||||||
///
|
///
|
||||||
/// \brief Unit Function (Versor)
|
/// \brief Unit Function (Versor)
|
||||||
/// \param q The Quaternion
|
/// \param q The Quaternion
|
||||||
/// \returns A Quaternion of `q` with norm `1`
|
/// \returns A Quaternion of \f$q\f$ with norm \f$1\f$
|
||||||
template<typename genType>
|
template<typename genType>
|
||||||
constexpr qua<genType> unit(const qua<genType>& q) {
|
constexpr qua<genType> unit(const qua<genType>& q) {
|
||||||
genType n = fennec::norm(q);
|
genType n = fennec::norm(q);
|
||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Default Constructor, creates a quaternion such that the real part is `1` and all others are `0`
|
/// \brief Default Constructor, creates a quaternion such that the real part is \f$1\f$ and all others are \f$0\f$
|
||||||
constexpr quaternion() {
|
constexpr quaternion() {
|
||||||
data = { 0, 0, 0, 1 };
|
data = { 0, 0, 0, 1 };
|
||||||
}
|
}
|
||||||
@@ -105,9 +105,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Component Constructor
|
/// \brief Component Constructor
|
||||||
/// \param w The scalar component
|
/// \param w The scalar component
|
||||||
/// \param x The coefficient of the `i` component
|
/// \param x The coefficient of the \f$i\f$ component
|
||||||
/// \param y The coefficient of the `j` component
|
/// \param y The coefficient of the \f$j\f$ component
|
||||||
/// \param z The coefficient of the `k` component
|
/// \param z The coefficient of the \f$k\f$ component
|
||||||
constexpr quaternion(scalar_t w, scalar_t x, scalar_t y, scalar_t z) {
|
constexpr quaternion(scalar_t w, scalar_t x, scalar_t y, scalar_t z) {
|
||||||
data = { x, y, z, w };
|
data = { x, y, z, w };
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ public:
|
|||||||
/// \brief Equality Operator
|
/// \brief Equality Operator
|
||||||
/// \param lhs the left hand side of the expression
|
/// \param lhs the left hand side of the expression
|
||||||
/// \param rhs the right hand side of the expression
|
/// \param rhs the right hand side of the expression
|
||||||
/// \returns `true` when all components of `lhs` and `rhs` are equal, false otherwise
|
/// \returns \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are equal, false otherwise
|
||||||
constexpr friend bool operator==(const quat_t& lhs, const quat_t& rhs) {
|
constexpr friend bool operator==(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return lhs.data == rhs.data;
|
return lhs.data == rhs.data;
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ public:
|
|||||||
/// \brief Inequality Operator
|
/// \brief Inequality Operator
|
||||||
/// \param lhs the left hand side of the expression
|
/// \param lhs the left hand side of the expression
|
||||||
/// \param rhs the right hand side of the expression
|
/// \param rhs the right hand side of the expression
|
||||||
/// \returns `true` when any component of `lhs` and `rhs` are not equal, false otherwise
|
/// \returns \f$true\f$ when any component of \f$lhs\f$ and \f$rhs\f$ are not equal, false otherwise
|
||||||
constexpr friend bool operator!=(const quat_t& lhs, const quat_t& rhs) {
|
constexpr friend bool operator!=(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return lhs.data != rhs.data;
|
return lhs.data != rhs.data;
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Unary Negation Operator
|
/// \brief Unary Negation Operator
|
||||||
/// \param rhs The quaternion to negate
|
/// \param rhs The quaternion to negate
|
||||||
/// \returns A quaternion with each component of `rhs` negated.
|
/// \returns A quaternion with each component of \f$rhs\f$ negated.
|
||||||
constexpr friend quat_t operator-(const quat_t& rhs) {
|
constexpr friend quat_t operator-(const quat_t& rhs) {
|
||||||
return quat_t(-rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
return quat_t(-rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Unary Conjugation Operator
|
/// \brief Unary Conjugation Operator
|
||||||
/// \param rhs The quaternion to conjugate
|
/// \param rhs The quaternion to conjugate
|
||||||
/// \returns A quaternion with each vector component of `rhs` negated.
|
/// \returns A quaternion with each vector component of \f$rhs\f$ negated.
|
||||||
constexpr friend quat_t operator~(const quat_t& rhs) {
|
constexpr friend quat_t operator~(const quat_t& rhs) {
|
||||||
return quat_t(rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
return quat_t(rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ public:
|
|||||||
/// \brief Quaternion-Scalar Multiplication Operator
|
/// \brief Quaternion-Scalar Multiplication Operator
|
||||||
/// \param lhs The quaternion
|
/// \param lhs The quaternion
|
||||||
/// \param rhs The scalar
|
/// \param rhs The scalar
|
||||||
/// \returns A quaternion with each component of `lhs` multiplied by `rhs`
|
/// \returns A quaternion with each component of \f$lhs\f$ multiplied by \f$rhs\f$
|
||||||
constexpr friend quat_t operator*(const quat_t& lhs, scalar_t rhs) {
|
constexpr friend quat_t operator*(const quat_t& lhs, scalar_t rhs) {
|
||||||
return quat_t(lhs.w * rhs, lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
|
return quat_t(lhs.w * rhs, lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ public:
|
|||||||
/// \brief Scalar-Quaternion Multiplication Operator
|
/// \brief Scalar-Quaternion Multiplication Operator
|
||||||
/// \param lhs The scalar
|
/// \param lhs The scalar
|
||||||
/// \param rhs The quaternion
|
/// \param rhs The quaternion
|
||||||
/// \returns A quaternion with each component of `rhs` multiplied by `lhs`
|
/// \returns A quaternion with each component of \f$rhs\f$ multiplied by \f$lhs\f$
|
||||||
constexpr friend quat_t operator*(scalar_t lhs, const quat_t& rhs) {
|
constexpr friend quat_t operator*(scalar_t lhs, const quat_t& rhs) {
|
||||||
return quat_t(lhs * rhs.w, lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
|
return quat_t(lhs * rhs.w, lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ public:
|
|||||||
/// \brief Quaternion-Scalar Division Operator
|
/// \brief Quaternion-Scalar Division Operator
|
||||||
/// \param lhs The quaternion
|
/// \param lhs The quaternion
|
||||||
/// \param rhs The scalar
|
/// \param rhs The scalar
|
||||||
/// \returns A quaternion with each component of `lhs` divided by `rhs`
|
/// \returns A quaternion with each component of \f$lhs\f$ divided by \f$rhs\f$
|
||||||
constexpr friend quat_t operator/(const quat_t& lhs, scalar_t rhs) {
|
constexpr friend quat_t operator/(const quat_t& lhs, scalar_t rhs) {
|
||||||
return quat_t(lhs.w / rhs, lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
|
return quat_t(lhs.w / rhs, lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
|
||||||
}
|
}
|
||||||
@@ -245,7 +245,7 @@ public:
|
|||||||
/// \brief Scalar-Quaternion Division Operator
|
/// \brief Scalar-Quaternion Division Operator
|
||||||
/// \param lhs The scalar
|
/// \param lhs The scalar
|
||||||
/// \param rhs The quaternion
|
/// \param rhs The quaternion
|
||||||
/// \returns A quaternion with each component of `rhs` divided by `lhs`
|
/// \returns A quaternion with each component of \f$rhs\f$ divided by \f$lhs\f$
|
||||||
constexpr friend quat_t operator/(scalar_t lhs, const quat_t& rhs) {
|
constexpr friend quat_t operator/(scalar_t lhs, const quat_t& rhs) {
|
||||||
return quat_t(lhs / rhs.w, lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
|
return quat_t(lhs / rhs.w, lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ public:
|
|||||||
/// \brief Quaternion-Scalar Multiplication Assignment Operator
|
/// \brief Quaternion-Scalar Multiplication Assignment Operator
|
||||||
/// \param lhs The quaternion
|
/// \param lhs The quaternion
|
||||||
/// \param rhs The scalar
|
/// \param rhs The scalar
|
||||||
/// \returns `lhs` with each component multiplied by `rhs`
|
/// \returns \f$lhs\f$ with each component multiplied by \f$rhs\f$
|
||||||
constexpr friend quat_t& operator*=(quat_t& lhs, scalar_t rhs) {
|
constexpr friend quat_t& operator*=(quat_t& lhs, scalar_t rhs) {
|
||||||
lhs.x *= rhs;
|
lhs.x *= rhs;
|
||||||
lhs.y *= rhs;
|
lhs.y *= rhs;
|
||||||
@@ -270,7 +270,7 @@ public:
|
|||||||
/// \brief Quaternion-Scalar Division Assignment Operator
|
/// \brief Quaternion-Scalar Division Assignment Operator
|
||||||
/// \param lhs The quaternion
|
/// \param lhs The quaternion
|
||||||
/// \param rhs The scalar
|
/// \param rhs The scalar
|
||||||
/// \returns `lhs` with each component divided by `rhs`
|
/// \returns \f$lhs\f$ with each component divided by \f$rhs\f$
|
||||||
constexpr friend quat_t& operator/=(const quat_t& lhs, scalar_t rhs) {
|
constexpr friend quat_t& operator/=(const quat_t& lhs, scalar_t rhs) {
|
||||||
lhs.x /= rhs;
|
lhs.x /= rhs;
|
||||||
lhs.y /= rhs;
|
lhs.y /= rhs;
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ struct matrix
|
|||||||
/// \brief matrix comparison operator
|
/// \brief matrix comparison operator
|
||||||
/// \param lhs the first matrix
|
/// \param lhs the first matrix
|
||||||
/// \param rhs the second matrix
|
/// \param rhs the second matrix
|
||||||
/// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are equal and \f$false\f$ otherwise
|
/// \returns a boolean value that contains \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are equal and \f$false\f$ otherwise
|
||||||
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) {
|
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) {
|
||||||
return lhs.data == rhs.data;
|
return lhs.data == rhs.data;
|
||||||
}
|
}
|
||||||
@@ -636,7 +636,7 @@ struct matrix
|
|||||||
/// \brief matrix comparison operator
|
/// \brief matrix comparison operator
|
||||||
/// \param lhs the first matrix
|
/// \param lhs the first matrix
|
||||||
/// \param rhs the second matrix
|
/// \param rhs the second matrix
|
||||||
/// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are not equal and \f$false\f$ otherwise
|
/// \returns a boolean value that contains \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are not equal and \f$false\f$ otherwise
|
||||||
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) {
|
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) {
|
||||||
return lhs.data != rhs.data;
|
return lhs.data != rhs.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,26 +23,26 @@
|
|||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief Backing storage struct for \ref fennec::swizzle "swizzle"
|
/// \brief Backing storage struct for \ref fennec::swizzle "swizzle"
|
||||||
// \tparam DataT Data Type
|
/// \tparam DataT Data Type
|
||||||
// \tparam ScalarT Element Types
|
/// \tparam ScalarT Element Types
|
||||||
// \tparam IndicesV Swizzle Order
|
/// \tparam IndicesV Swizzle Order
|
||||||
template<typename DataT, typename ScalarT, size_t...IndicesV>
|
template<typename DataT, typename ScalarT, size_t...IndicesV>
|
||||||
struct swizzle_storage
|
struct swizzle_storage
|
||||||
{
|
{
|
||||||
//
|
///
|
||||||
// \brief an array containing the indices of this swizzle
|
/// \brief an array containing the indices of this swizzle
|
||||||
inline static constexpr size_t indices[] = { IndicesV... };
|
inline static constexpr size_t indices[] = { IndicesV... };
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief an array containing the scalar values of this swizzle
|
/// \brief an array containing the scalar values of this swizzle
|
||||||
DataT data;
|
DataT data;
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief element access, returns a copy of the value at index \p i
|
/// \brief element access, returns a copy of the value at index \p i
|
||||||
// \param i the index
|
/// \param i the index
|
||||||
// \returns a copy of the scalar value at index \p i
|
/// \returns a copy of the scalar value at index \p i
|
||||||
constexpr ScalarT operator[](size_t i) const noexcept {
|
constexpr ScalarT operator[](size_t i) const noexcept {
|
||||||
return data[indices[i]];
|
return data[indices[i]];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,33 +46,33 @@
|
|||||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_vector_types">
|
/// <table width="100%" class="fieldtable" id="table_fennec_math_vector_types">
|
||||||
/// <tr><th>Type <th>Corresponding Type <th>Brief
|
/// <tr><th>Type <th>Corresponding Type <th>Brief
|
||||||
/// <tr><th colspan=3 style="text-align: center;">Floats
|
/// <tr><th colspan=3 style="text-align: center;">Floats
|
||||||
/// <tr><td>```vec2``` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
|
/// <tr><td>``\f$vec2\f$`` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
|
||||||
/// <tr><td>```vec3``` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
|
/// <tr><td>``\f$vec3\f$`` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
|
||||||
/// <tr><td>```vec4``` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
|
/// <tr><td>``\f$vec4\f$`` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
|
||||||
/// <tr><th colspan=3 style="text-align: center;">Doubles
|
/// <tr><th colspan=3 style="text-align: center;">Doubles
|
||||||
/// <tr><td>```dvec2```<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
|
/// <tr><td>``\f$dvec2\f$``<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
|
||||||
/// <tr><td>```dvec3```<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
|
/// <tr><td>``\f$dvec3\f$``<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
|
||||||
/// <tr><td>```dvec4```<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
|
/// <tr><td>``\f$dvec4\f$``<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
|
||||||
/// <tr><th colspan=3 style="text-align: center;">Booleans
|
/// <tr><th colspan=3 style="text-align: center;">Booleans
|
||||||
/// <tr><td>```bvec2``` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
|
/// <tr><td>``\f$bvec2\f$`` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
|
||||||
/// <tr><td>```bvec3``` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
|
/// <tr><td>``\f$bvec3\f$`` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
|
||||||
/// <tr><td>```bvec4``` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
|
/// <tr><td>``\f$bvec4\f$`` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
|
||||||
/// <tr><th colspan=3 style="text-align: center;">Integers
|
/// <tr><th colspan=3 style="text-align: center;">Integers
|
||||||
/// <tr><td>```ivec2``` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
|
/// <tr><td>``\f$ivec2\f$`` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
|
||||||
/// <tr><td>```ivec3``` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
|
/// <tr><td>``\f$ivec3\f$`` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
|
||||||
/// <tr><td>```ivec4``` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
|
/// <tr><td>``\f$ivec4\f$`` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
|
||||||
/// <tr><th colspan=3 style="text-align: center;">Unsigned Integers
|
/// <tr><th colspan=3 style="text-align: center;">Unsigned Integers
|
||||||
/// <tr><td>```uvec2``` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
|
/// <tr><td>``\f$uvec2\f$`` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
|
||||||
/// <tr><td>```uvec3``` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
|
/// <tr><td>``\f$uvec3\f$`` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
|
||||||
/// <tr><td>```uvec4``` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
|
/// <tr><td>``\f$uvec4\f$`` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \section vector_components Components
|
/// \section vector_components Components
|
||||||
///
|
///
|
||||||
/// Vectors are usually made up of one to four components, named ```x```, ```y```, ```z```, and ```w```.
|
/// Vectors are usually made up of one to four components, named ``\f$x\f$``, ``\f$y\f$``, ``\f$z\f$``, and ``\f$w\f$``.
|
||||||
/// Each component also has aliases for usage in colors ```rgba```, and texture coordinates ```stpq```. Accessing a
|
/// Each component also has aliases for usage in colors ``\f$rgba\f$``, and texture coordinates ``\f$stpq\f$``. Accessing a
|
||||||
/// component outside the vector will cause an error at compile time, for example:
|
/// component outside the vector will cause an error at compile time, for example:
|
||||||
///
|
///
|
||||||
/// \code{.cpp}
|
/// \code{.cpp}
|
||||||
|
|||||||
@@ -30,54 +30,55 @@
|
|||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief helper class for generating vectors
|
/// \brief helper class for generating vectors
|
||||||
// \tparam scalar base scalar type
|
/// \tparam scalar base scalar type
|
||||||
// \tparam size size of the vector type
|
/// \tparam size size of the vector type
|
||||||
template<typename scalar, size_t size>
|
template<typename scalar, size_t size>
|
||||||
struct vector_base_type_helper
|
struct vector_base_type_helper
|
||||||
{
|
{
|
||||||
//
|
///
|
||||||
// \var SizeV
|
/// \var SizeV
|
||||||
// \brief size of the vector type
|
/// \brief size of the vector type
|
||||||
inline static constexpr size_t SizeV = size;
|
inline static constexpr size_t SizeV = size;
|
||||||
|
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief Base scalar type
|
/// \brief Base scalar type
|
||||||
using ScalarT = scalar;
|
using ScalarT = scalar;
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief Base vector type
|
/// \brief Base vector type
|
||||||
using VectorT = vec<ScalarT, SizeV>;
|
using VectorT = vec<ScalarT, SizeV>;
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief Backing array holding the elements
|
/// \brief Backing array holding the elements
|
||||||
using DataT = array<ScalarT, SizeV>;
|
using DataT = array<ScalarT, SizeV>;
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief Helper for generating a swizzle from a set of indices
|
/// \brief Helper for generating a swizzle from a set of indices
|
||||||
// \tparam IndicesV Indices of the vector to pull from
|
/// \tparam IndicesV Indices of the vector to pull from
|
||||||
template<size_t...IndicesV> struct SwizzleGen
|
template<size_t...IndicesV> struct SwizzleGen
|
||||||
{
|
{
|
||||||
// \brief generated swizzle type
|
// \brief generated swizzle type
|
||||||
using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>;
|
using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for single component swizzles to decay into a scalar
|
///
|
||||||
|
/// \tparam IndicesV Indices of the vector to pull from
|
||||||
template<size_t IndexV> struct SwizzleGen<IndexV>
|
template<size_t IndexV> struct SwizzleGen<IndexV>
|
||||||
{
|
{
|
||||||
// \brief decayed scalar type
|
// \brief decayed scalar type
|
||||||
using type = ScalarT;
|
using type = ScalarT;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief backing storage type
|
/// \brief backing storage type
|
||||||
using StorageT = vector_storage<SizeV, SwizzleGen, DataT>;
|
using StorageT = vector_storage<SizeV, SwizzleGen, DataT>;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief helper for getting the storage type of the vector constructed with the provided size and scalar type
|
/// \brief helper for getting the storage type of the vector constructed with the provided size and scalar type
|
||||||
template<typename ScalarT, size_t SizeV>
|
template<typename ScalarT, size_t SizeV>
|
||||||
using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT;
|
using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT;
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,16 @@
|
|||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
///
|
||||||
// \brief backing storage type for vectors
|
/// \brief backing storage type for vectors
|
||||||
// \tparam SizeV size of the vector
|
/// \tparam SizeV size of the vector
|
||||||
// \tparam SwizzleGenT generator for swizzles
|
/// \tparam SwizzleGenT generator for swizzles
|
||||||
// \tparam DataT backing data type
|
/// \tparam DataT backing data type
|
||||||
template<size_t SizeV, template<size_t...> class SwizzleGenT, typename DataT> struct vector_storage;
|
template<size_t SizeV, template<size_t...> class SwizzleGenT, typename DataT> struct vector_storage;
|
||||||
|
|
||||||
|
///
|
||||||
// specialization for single component vectors
|
/// \tparam SwizzleGenT generator for swizzles
|
||||||
|
/// \tparam DataT backing data type
|
||||||
template <template <size_t...> class SwizzleGenT, typename DataT>
|
template <template <size_t...> class SwizzleGenT, typename DataT>
|
||||||
struct vector_storage<1, SwizzleGenT, DataT>
|
struct vector_storage<1, SwizzleGenT, DataT>
|
||||||
{
|
{
|
||||||
@@ -65,7 +66,9 @@ namespace fennec::detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// specialization for two component vectors
|
///
|
||||||
|
/// \tparam SwizzleGenT generator for swizzles
|
||||||
|
/// \tparam DataT backing data type
|
||||||
template <template <size_t...> class SwizzleGenT, typename DataT>
|
template <template <size_t...> class SwizzleGenT, typename DataT>
|
||||||
struct vector_storage<2, SwizzleGenT, DataT>
|
struct vector_storage<2, SwizzleGenT, DataT>
|
||||||
{
|
{
|
||||||
@@ -114,7 +117,9 @@ namespace fennec::detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// specialization for three component vectors
|
///
|
||||||
|
/// \tparam SwizzleGenT generator for swizzles
|
||||||
|
/// \tparam DataT backing data type
|
||||||
template <template <size_t...> class SwizzleGenT, typename DataT>
|
template <template <size_t...> class SwizzleGenT, typename DataT>
|
||||||
struct vector_storage<3, SwizzleGenT, DataT>
|
struct vector_storage<3, SwizzleGenT, DataT>
|
||||||
{
|
{
|
||||||
@@ -250,7 +255,9 @@ namespace fennec::detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// specialization for four component vectors
|
///
|
||||||
|
/// \tparam SwizzleGenT generator for swizzles
|
||||||
|
/// \tparam DataT backing data type
|
||||||
template <template <size_t...> class SwizzleGenT, typename DataT>
|
template <template <size_t...> class SwizzleGenT, typename DataT>
|
||||||
struct vector_storage<4, SwizzleGenT, DataT>
|
struct vector_storage<4, SwizzleGenT, DataT>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
/// \brief Checks if this allocator type is always equal to another allocator of similar type
|
/// \brief Checks if this allocator type is always equal to another allocator of similar type
|
||||||
using is_always_equal = detect_t<false_type, _is_always_equal, Alloc>;
|
using is_always_equal = detect_t<false_type, _is_always_equal, Alloc>;
|
||||||
|
|
||||||
/// \brief Rebinds the allocator type to produce an element type of type `TypeT`
|
/// \brief Rebinds the allocator type to produce an element type of type \f$TypeT\f$
|
||||||
template<typename TypeT> using rebind = typename _rebind<Alloc, TypeT>::type;
|
template<typename TypeT> using rebind = typename _rebind<Alloc, TypeT>::type;
|
||||||
|
|
||||||
// TODO: allocator_traits static functions
|
// TODO: allocator_traits static functions
|
||||||
@@ -138,7 +138,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocator implementation, uses `new` and `delete` operators.
|
/// \brief Allocator implementation, uses \f$new\f$ and \f$delete\f$ operators.
|
||||||
/// \tparam T The data type to allocate
|
/// \tparam T The data type to allocate
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class allocator
|
class allocator
|
||||||
@@ -171,34 +171,34 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Equality operator
|
/// \brief Equality operator
|
||||||
/// \returns `true`
|
/// \returns \f$true\f$
|
||||||
constexpr bool_t operator==(const allocator&) {
|
constexpr bool_t operator==(const allocator&) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Inequality operator
|
/// \brief Inequality operator
|
||||||
/// \returns `false`
|
/// \returns \f$false\f$
|
||||||
constexpr bool_t operator!=(const allocator&) {
|
constexpr bool_t operator!=(const allocator&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Equality operator for allocators of same type but with different data type
|
/// \brief Equality operator for allocators of same type but with different data type
|
||||||
/// \returns `false`
|
/// \returns \f$false\f$
|
||||||
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Inequality operator for allocators of same type but with different data type
|
/// \brief Inequality operator for allocators of same type but with different data type
|
||||||
/// \returns `true`
|
/// \returns \f$true\f$
|
||||||
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
|
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \returns A pointer to the allocated block
|
/// \returns A pointer to the allocated block
|
||||||
constexpr T* allocate(size_t n) {
|
constexpr T* allocate(size_t n) {
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
|
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \param align The alignment
|
/// \param align The alignment
|
||||||
/// \returns A pointer to the allocated block
|
/// \returns A pointer to the allocated block
|
||||||
@@ -215,14 +215,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Deallocate a block of memory with type `T`
|
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||||
/// \param ptr The block to release
|
/// \param ptr The block to release
|
||||||
constexpr void deallocate(T* ptr) {
|
constexpr void deallocate(T* ptr) {
|
||||||
return ::operator delete(ptr);
|
return ::operator delete(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Deallocate a block of memory with type `T`
|
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||||
/// \param ptr The block to release
|
/// \param ptr The block to release
|
||||||
/// \param align The alignment
|
/// \param align The alignment
|
||||||
constexpr void deallocate(T* ptr, align_t align) {
|
constexpr void deallocate(T* ptr, align_t align) {
|
||||||
@@ -232,7 +232,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocator implementation, uses `new` and `delete` operators.
|
/// \brief Allocator implementation, uses \f$new\f$ and \f$delete\f$ operators.
|
||||||
/// \tparam T The data type to allocate
|
/// \tparam T The data type to allocate
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class allocator<T[]>
|
class allocator<T[]>
|
||||||
@@ -266,34 +266,34 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Equality operator
|
/// \brief Equality operator
|
||||||
/// \returns `true`
|
/// \returns \f$true\f$
|
||||||
constexpr bool_t operator==(const allocator&) {
|
constexpr bool_t operator==(const allocator&) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Inequality operator
|
/// \brief Inequality operator
|
||||||
/// \returns `false`
|
/// \returns \f$false\f$
|
||||||
constexpr bool_t operator!=(const allocator&) {
|
constexpr bool_t operator!=(const allocator&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Equality operator for allocators of same type but with different data type
|
/// \brief Equality operator for allocators of same type but with different data type
|
||||||
/// \returns `false`
|
/// \returns \f$false\f$
|
||||||
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Inequality operator for allocators of same type but with different data type
|
/// \brief Inequality operator for allocators of same type but with different data type
|
||||||
/// \returns `true`
|
/// \returns \f$true\f$
|
||||||
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
|
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \returns A pointer to the allocated block
|
/// \returns A pointer to the allocated block
|
||||||
constexpr T* allocate(size_t n) {
|
constexpr T* allocate(size_t n) {
|
||||||
@@ -301,7 +301,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
|
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||||
/// \param n The number of elements
|
/// \param n The number of elements
|
||||||
/// \param align The alignment
|
/// \param align The alignment
|
||||||
/// \returns A pointer to the allocated block
|
/// \returns A pointer to the allocated block
|
||||||
@@ -310,14 +310,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Deallocate a block of memory with type `T`
|
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||||
/// \param ptr The block to release
|
/// \param ptr The block to release
|
||||||
constexpr void deallocate(T* ptr) {
|
constexpr void deallocate(T* ptr) {
|
||||||
return ::operator delete[](ptr);
|
return ::operator delete[](ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Deallocate a block of memory with type `T`
|
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||||
/// \param ptr The block to release
|
/// \param ptr The block to release
|
||||||
/// \param align The alignment
|
/// \param align The alignment
|
||||||
constexpr void deallocate(T* ptr, align_t align) {
|
constexpr void deallocate(T* ptr, align_t align) {
|
||||||
@@ -353,14 +353,14 @@ public:
|
|||||||
// Cosntructors ========================================================================================================
|
// Cosntructors ========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Default Constructor, initializes internal data to `null` and the capacity to `0`
|
/// \brief Default Constructor, initializes internal data to \f$null\f$ and the capacity to \f$0\f$
|
||||||
constexpr allocation() noexcept
|
constexpr allocation() noexcept
|
||||||
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
explicit constexpr allocation(size_t n) noexcept
|
explicit constexpr allocation(size_t n) noexcept
|
||||||
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
||||||
callocate(n);
|
callocate(n);
|
||||||
@@ -378,7 +378,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment of the allocation
|
/// \param align The alignment of the allocation
|
||||||
constexpr allocation(size_t n, align_t align) noexcept
|
constexpr allocation(size_t n, align_t align) noexcept
|
||||||
: _data(nullptr)
|
: _data(nullptr)
|
||||||
@@ -402,7 +402,7 @@ public:
|
|||||||
/// \brief Allocator Constructor
|
/// \brief Allocator Constructor
|
||||||
/// \param alloc The allocation object to copy.
|
/// \param alloc The allocation object to copy.
|
||||||
///
|
///
|
||||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||||
explicit constexpr allocation(const alloc_t& alloc) noexcept
|
explicit constexpr allocation(const alloc_t& alloc) noexcept
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _data(nullptr)
|
, _data(nullptr)
|
||||||
@@ -412,10 +412,10 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocator Constructor
|
/// \brief Sized Allocator Constructor
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param alloc The allocation object to copy.
|
/// \param alloc The allocation object to copy.
|
||||||
///
|
///
|
||||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||||
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _data(nullptr)
|
, _data(nullptr)
|
||||||
@@ -431,7 +431,7 @@ public:
|
|||||||
/// \param n the number of elements
|
/// \param n the number of elements
|
||||||
/// \param alloc The allocation object to copy.
|
/// \param alloc The allocation object to copy.
|
||||||
///
|
///
|
||||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||||
constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
|
constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
|
||||||
: allocation(n, alloc) {
|
: allocation(n, alloc) {
|
||||||
fennec::memmove(static_cast<void*>(_data), data, n);
|
fennec::memmove(static_cast<void*>(_data), data, n);
|
||||||
@@ -439,11 +439,11 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocator Constructor
|
/// \brief Sized Allocator Constructor
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment of the allocation
|
/// \param align The alignment of the allocation
|
||||||
/// \param alloc The allocation object to copy.
|
/// \param alloc The allocation object to copy.
|
||||||
///
|
///
|
||||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||||
constexpr allocation(size_t n, align_t align, const alloc_t& alloc) noexcept
|
constexpr allocation(size_t n, align_t align, const alloc_t& alloc) noexcept
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _data(nullptr)
|
, _data(nullptr)
|
||||||
@@ -460,7 +460,7 @@ public:
|
|||||||
/// \param align The alignment of the allocation
|
/// \param align The alignment of the allocation
|
||||||
/// \param alloc The allocation object to copy.
|
/// \param alloc The allocation object to copy.
|
||||||
///
|
///
|
||||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||||
constexpr allocation(const T* data, size_t n, align_t align, const alloc_t& alloc)
|
constexpr allocation(const T* data, size_t n, align_t align, const alloc_t& alloc)
|
||||||
: allocation(n, align, alloc) {
|
: allocation(n, align, alloc) {
|
||||||
fennec::memmove(_data, data, n);
|
fennec::memmove(_data, data, n);
|
||||||
@@ -478,7 +478,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor, moves the data in `alloc` to the new object and cleans `alloc` so that it
|
/// \brief Move Constructor, moves the data in \f$alloc\f$ to the new object and cleans \f$alloc\f$ so that it
|
||||||
/// can safely destruct
|
/// can safely destruct
|
||||||
/// \param alloc The allocation to move
|
/// \param alloc The allocation to move
|
||||||
constexpr allocation(allocation&& alloc) noexcept
|
constexpr allocation(allocation&& alloc) noexcept
|
||||||
@@ -505,7 +505,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Copy Assignment Operator
|
/// \brief Copy Assignment Operator
|
||||||
/// \param alloc the allocation to copy
|
/// \param alloc the allocation to copy
|
||||||
/// \returns a reference to `this`
|
/// \returns a reference to \f$this\f$
|
||||||
constexpr allocation& operator=(const allocation& alloc) {
|
constexpr allocation& operator=(const allocation& alloc) {
|
||||||
allocation::allocate(alloc.capacity(), alloc.alignment());
|
allocation::allocate(alloc.capacity(), alloc.alignment());
|
||||||
fennec::memmove(_data, alloc, size());
|
fennec::memmove(_data, alloc, size());
|
||||||
@@ -515,7 +515,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Move Assignment Operator
|
/// \brief Move Assignment Operator
|
||||||
/// \param alloc the allocation to copy
|
/// \param alloc the allocation to copy
|
||||||
/// \returns a reference to `this`
|
/// \returns a reference to \f$this\f$
|
||||||
constexpr allocation& operator=(allocation&& alloc) noexcept {
|
constexpr allocation& operator=(allocation&& alloc) noexcept {
|
||||||
|
|
||||||
// Copy contents
|
// Copy contents
|
||||||
@@ -534,7 +534,7 @@ public:
|
|||||||
/// \brief Allocate a block of memory for the allocation.
|
/// \brief Allocate a block of memory for the allocation.
|
||||||
/// If there is already an allocated block of memory, the previous allocation is released.
|
/// If there is already an allocated block of memory, the previous allocation is released.
|
||||||
///
|
///
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment to use
|
/// \param align The alignment to use
|
||||||
constexpr void allocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void allocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
deallocate();
|
deallocate();
|
||||||
@@ -550,7 +550,7 @@ public:
|
|||||||
/// \brief Allocate a block of memory for the allocation.
|
/// \brief Allocate a block of memory for the allocation.
|
||||||
/// If there is already an allocated block of memory, the previous allocation is released.
|
/// If there is already an allocated block of memory, the previous allocation is released.
|
||||||
///
|
///
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment to use
|
/// \param align The alignment to use
|
||||||
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
allocate(n, align);
|
allocate(n, align);
|
||||||
@@ -577,7 +577,7 @@ public:
|
|||||||
/// \brief Reallocate the block with a new size.
|
/// \brief Reallocate the block with a new size.
|
||||||
/// Contents are copied to the new allocation.
|
/// Contents are copied to the new allocation.
|
||||||
///
|
///
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment to use
|
/// \param align The alignment to use
|
||||||
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
if (_data == nullptr) {
|
if (_data == nullptr) {
|
||||||
@@ -599,7 +599,7 @@ public:
|
|||||||
/// \brief Reallocate the block with a new size.
|
/// \brief Reallocate the block with a new size.
|
||||||
/// Contents are copied to the new allocation.
|
/// Contents are copied to the new allocation.
|
||||||
///
|
///
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||||
/// \param align The alignment to use
|
/// \param align The alignment to use
|
||||||
constexpr void creallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void creallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
if (_data == nullptr) {
|
if (_data == nullptr) {
|
||||||
@@ -626,7 +626,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param i The index to access
|
/// \param i The index to access
|
||||||
/// \returns a reference to the value at position `i` in the allocation
|
/// \returns a reference to the value at position \f$i\f$ in the allocation
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assertd(i < capacity(), "Array Out of Bounds");
|
assertd(i < capacity(), "Array Out of Bounds");
|
||||||
return _data[i];
|
return _data[i];
|
||||||
@@ -635,7 +635,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i The index to access
|
/// \param i The index to access
|
||||||
/// \returns a reference to the value at position `i` in the allocation
|
/// \returns a reference to the value at position \f$i\f$ in the allocation
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assertd(i < capacity(), "Array Out of Bounds");
|
assertd(i < capacity(), "Array Out of Bounds");
|
||||||
return _data[i];
|
return _data[i];
|
||||||
@@ -697,7 +697,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for the number of elements `n` of type `T` that the allocation can hold.
|
/// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold.
|
||||||
/// \returns the size of the allocation in elements
|
/// \returns the size of the allocation in elements
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
return _capacity;
|
return _capacity;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a reference to the byte at `i`
|
/// \returns a reference to the byte at \f$i\f$
|
||||||
constexpr byte_t& operator[](int i) {
|
constexpr byte_t& operator[](int i) {
|
||||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||||
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Const Array Access Operator
|
/// \brief Const Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a copy of the byte at `i`
|
/// \returns a copy of the byte at \f$i\f$
|
||||||
constexpr byte_t operator[](int i) const {
|
constexpr byte_t operator[](int i) const {
|
||||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||||
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
||||||
@@ -109,7 +109,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Cast Function
|
/// \brief Cast Function
|
||||||
/// \tparam T type to cast to
|
/// \tparam T type to cast to
|
||||||
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
|
/// \returns a pointer to the underlying buffer interpreted as an array of \f$T\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T* cast() {
|
constexpr T* cast() {
|
||||||
void* temp = _arr;
|
void* temp = _arr;
|
||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Const Cast Function
|
/// \brief Const Cast Function
|
||||||
/// \tparam T type to cast to
|
/// \tparam T type to cast to
|
||||||
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
|
/// \returns a pointer to the underlying buffer interpreted as an array of \f$T\f$
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr const T* cast() const {
|
constexpr const T* cast() const {
|
||||||
const void* temp = _carr;
|
const void* temp = _carr;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace fennec
|
|||||||
{
|
{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Struct for wrapping C++ `delete`
|
/// \brief Struct for wrapping C++ \f$delete\f$
|
||||||
/// \tparam TypeT The type of the buffer to be deleted
|
/// \tparam TypeT The type of the buffer to be deleted
|
||||||
template<typename TypeT>
|
template<typename TypeT>
|
||||||
struct default_delete
|
struct default_delete
|
||||||
@@ -42,7 +42,7 @@ struct default_delete
|
|||||||
constexpr default_delete(const default_delete<ConvT>&) noexcept {}
|
constexpr default_delete(const default_delete<ConvT>&) noexcept {}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Function Call Operator, calls `delete` on `ptr`
|
/// \brief Function Call Operator, calls \f$delete\f$ on \f$ptr\f$
|
||||||
/// \param ptr Memory resource to delete
|
/// \param ptr Memory resource to delete
|
||||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||||
@@ -51,7 +51,8 @@ struct default_delete
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Overload for Arrays
|
///
|
||||||
|
/// \tparam TypeT The type of the buffer to be deleted
|
||||||
template<typename TypeT>
|
template<typename TypeT>
|
||||||
struct default_delete<TypeT[]>
|
struct default_delete<TypeT[]>
|
||||||
{
|
{
|
||||||
@@ -66,7 +67,7 @@ struct default_delete<TypeT[]>
|
|||||||
constexpr default_delete(const default_delete<ConvT(*)[]>&) noexcept {}
|
constexpr default_delete(const default_delete<ConvT(*)[]>&) noexcept {}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Function Call Operator, calls `delete` on `ptr`
|
/// \brief Function Call Operator, calls \f$delete\f$ on \f$ptr\f$
|
||||||
/// \param ptr Memory resource to delete
|
/// \param ptr Memory resource to delete
|
||||||
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
|
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
|
||||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||||
@@ -107,7 +108,7 @@ public:
|
|||||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr, delete_t()) {}
|
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr, delete_t()) {}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
/// \brief Pointer Constructor, creates a unique_ptr that owns \f$ptr\f$ with deleter \f$del\f$
|
||||||
/// \param ptr The resource to own
|
/// \param ptr The resource to own
|
||||||
/// \param del The deleter
|
/// \param del The deleter
|
||||||
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del = delete_t())
|
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del = delete_t())
|
||||||
@@ -116,7 +117,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor, transfers ownership from `other`
|
/// \brief Move Constructor, transfers ownership from \f$other\f$
|
||||||
/// \param other The unique_ptr to take ownership from
|
/// \param other The unique_ptr to take ownership from
|
||||||
constexpr unique_ptr(unique_ptr&& other)
|
constexpr unique_ptr(unique_ptr&& other)
|
||||||
: _handle(other._handle) {
|
: _handle(other._handle) {
|
||||||
@@ -161,7 +162,7 @@ public:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_t get() {
|
pointer_t get() const {
|
||||||
return _handle;
|
return _handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +189,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Creates a unique pointer holding an object of type `TypeT`
|
/// \brief Creates a unique pointer holding an object of type \f$TypeT\f$
|
||||||
/// \tparam TypeT The type
|
/// \tparam TypeT The type
|
||||||
/// \tparam ArgsT The constructor arguments, automatically deduced
|
/// \tparam ArgsT The constructor arguments, automatically deduced
|
||||||
/// \param args The constructor arguments
|
/// \param args The constructor arguments
|
||||||
/// \returns A unique pointer holding a heap allocated object of type `TypeT` constructed with arguments `args`
|
/// \returns A unique pointer holding a heap allocated object of type \f$TypeT\f$ constructed with arguments \f$args\f$
|
||||||
template<typename TypeT, typename...ArgsT>
|
template<typename TypeT, typename...ArgsT>
|
||||||
unique_ptr<TypeT> make_unique(ArgsT&&...args) {
|
unique_ptr<TypeT> make_unique(ArgsT&&...args) {
|
||||||
return unique_ptr<TypeT>(new TypeT(fennec::forward<ArgsT>(args)...));
|
return unique_ptr<TypeT>(new TypeT(fennec::forward<ArgsT>(args)...));
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ class display_server;
|
|||||||
///
|
///
|
||||||
/// \details An implementation for a display server should inherit `display_server_base` and note the following:
|
/// \details An implementation for a display server should inherit `display_server_base` and note the following:
|
||||||
///
|
///
|
||||||
/// For a server type `DisplayT`; any `gfxcontext` implementation that wishes to implement `DisplayT`
|
/// For a server type \f$DisplayT\f$; any \f$gfxcontext\f$ implementation that wishes to implement \f$DisplayT\f$
|
||||||
/// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be
|
/// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be
|
||||||
/// called for the `gfxcontext` implementation.
|
/// called for the \f$gfxcontext\f$ implementation.
|
||||||
class display_server : public type_registry<display_server, platform*> {
|
class display_server : public type_registry<display_server, platform*> {
|
||||||
// Typedefs/Constants/Enums ============================================================================================
|
// Typedefs/Constants/Enums ============================================================================================
|
||||||
public:
|
public:
|
||||||
@@ -134,6 +134,8 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Interface resembling the API for a display server of an operating system, e.g. Linux X11/Wayland
|
||||||
template<typename DisplayT, typename WindowT>
|
template<typename DisplayT, typename WindowT>
|
||||||
class display_server_base : public display_server, public type_registry<gfxcontext, DisplayT*> {
|
class display_server_base : public display_server, public type_registry<gfxcontext, DisplayT*> {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ struct singleton {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static T& instance() requires(is_default_constructible_v<T> and not is_pointer_v<T>) {
|
static T& instance() requires(not is_pointer_v<T>) {
|
||||||
static T instance;
|
static T instance;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,25 +65,25 @@ struct type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if this is a complete type, false otherwise
|
/// \returns \f$true\f$ if this is a complete type, false otherwise
|
||||||
bool is_complete() const {
|
bool is_complete() const {
|
||||||
return _data ? _data->properties.test(type_data::property_complete) : false;
|
return _data ? _data->properties.test(type_data::property_complete) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if this type fulfills the [C++11 range-initializer](https://en.cppreference.com/w/cpp/language/range-for.html), false otherwise
|
/// \returns \f$true\f$ if this type fulfills the [C++11 range-initializer](https://en.cppreference.com/w/cpp/language/range-for.html), false otherwise
|
||||||
bool is_iterable() const {
|
bool is_iterable() const {
|
||||||
return _data ? _data->properties.test(type_data::property_iterable) : false;
|
return _data ? _data->properties.test(type_data::property_iterable) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if this type implements `operator[]` with a single parameter of integral type, false otherwise
|
/// \returns \f$true\f$ if this type implements `operator[]` with a single parameter of integral type, false otherwise
|
||||||
bool is_indexable() const {
|
bool is_indexable() const {
|
||||||
return _data ? _data->properties.test(type_data::property_indexable) : false;
|
return _data ? _data->properties.test(type_data::property_indexable) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if this type implements `operator[]` with a single parameter of type `type::key_t`
|
/// \returns \f$true\f$ if this type implements `operator[]` with a single parameter of type `type::key_t`
|
||||||
bool is_mappable() const {
|
bool is_mappable() const {
|
||||||
return _data ? _data->properties.test(type_data::property_mappable) : false;
|
return _data ? _data->properties.test(type_data::property_mappable) : false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,15 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Base Component Functionality
|
||||||
class component {
|
class component {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// MEMBERS =============================================================================================================
|
// MEMBERS =============================================================================================================
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// \brief reference to the
|
||||||
scene_node* const node;
|
scene_node* const node;
|
||||||
|
|
||||||
component(scene_node* node)
|
component(scene_node* node)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define FENNEC_SCENE_SCENE_H
|
#define FENNEC_SCENE_SCENE_H
|
||||||
|
|
||||||
#include <fennec/containers/rdtree.h>
|
#include <fennec/containers/rdtree.h>
|
||||||
|
#include <fennec/memory/pointers.h>
|
||||||
#include <fennec/string/string.h>
|
#include <fennec/string/string.h>
|
||||||
|
|
||||||
#include <fennec/scene/forward.h>
|
#include <fennec/scene/forward.h>
|
||||||
@@ -33,7 +34,13 @@ namespace fennec
|
|||||||
/// \details This structure only contains the names of nodes and defers storage for components to
|
/// \details This structure only contains the names of nodes and defers storage for components to
|
||||||
/// their respective systems. Simple components may be isolated, \see components.h for more info.
|
/// their respective systems. Simple components may be isolated, \see components.h for more info.
|
||||||
/// The hierarchy should be displayed using pre-order traversal.
|
/// The hierarchy should be displayed using pre-order traversal.
|
||||||
class scene : private rdtree<scene_node*> {
|
class scene {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
private:
|
||||||
|
using elem_t = unique_ptr<scene_node>;
|
||||||
|
using table_t = rdtree<elem_t>;
|
||||||
|
|
||||||
|
|
||||||
// Access ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
public:
|
public:
|
||||||
@@ -41,17 +48,18 @@ public:
|
|||||||
/// \brief Find a node by name.
|
/// \brief Find a node by name.
|
||||||
/// \details If multiple nodes have the same name, finds the first one in pre-order traversal.
|
/// \details If multiple nodes have the same name, finds the first one in pre-order traversal.
|
||||||
/// \param name The name of the node to search for
|
/// \param name The name of the node to search for
|
||||||
/// \returns The id of the node, `npos` if not found.
|
/// \returns The id of the node, \f$npos\f$ if not found.
|
||||||
scene_node* operator[](const cstring& name) const;
|
scene_node* operator[](const cstring& name) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Find a node by name.
|
/// \brief Find a node by name.
|
||||||
/// \details If multiple nodes have the same name, finds the first one in pre-order traversal.
|
/// \details If multiple nodes have the same name, finds the first one in pre-order traversal.
|
||||||
/// \param name The name of the node to search for
|
/// \param name The name of the node to search for
|
||||||
/// \returns The id of the node, `npos` if not found.
|
/// \returns The id of the node, \f$npos\f$ if not found.
|
||||||
scene_node* operator[](const string& name) const;
|
scene_node* operator[](const string& name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
table_t _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,10 +283,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
|
||||||
/// \param c the character to find
|
/// \param c the character to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(char c, size_t i = 0) const {
|
constexpr size_t find(char c, size_t i = 0) const {
|
||||||
if (i >= _size) { // bounds check
|
if (i >= _size) { // bounds check
|
||||||
return _size;
|
return _size;
|
||||||
@@ -297,10 +297,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
||||||
if (i + str._size > _size) { // bounds check
|
if (i + str._size > _size) { // bounds check
|
||||||
return _size;
|
return _size;
|
||||||
@@ -311,10 +311,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
/// \brief Finds the index of the last occurrence of \f$c\f$ in the string.
|
||||||
/// \param c the string to find
|
/// \param c the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return _size;
|
return _size;
|
||||||
@@ -328,10 +328,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return _size;
|
return _size;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
/// \brief Sized Constructor, initializes a null-terminated string of size \f$n\f$ with `'c'...`
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \param c the character to fill with
|
/// \param c the character to fill with
|
||||||
///
|
///
|
||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Alloc Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
/// \brief Sized Alloc Constructor, initializes a null-terminated string of size \f$n\f$ with `'c'...`
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \param c the character to fill with
|
/// \param c the character to fill with
|
||||||
/// \param alloc The allocator to use
|
/// \param alloc The allocator to use
|
||||||
@@ -187,7 +187,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if the string contains no characters, `false` otherwise.
|
/// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
/// \param i An offset to start with in `this`
|
/// \param i An offset to start with in \f$this\f$
|
||||||
/// \param n The number of characters to compare
|
/// \param n The number of characters to compare
|
||||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||||
/// current locale, otherwise a positive value.
|
/// current locale, otherwise a positive value.
|
||||||
@@ -254,7 +254,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Comparison
|
/// \brief String Comparison
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \param n The number of characters to compare
|
/// \param n The number of characters to compare
|
||||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||||
/// current locale, otherwise a positive value.
|
/// current locale, otherwise a positive value.
|
||||||
@@ -285,17 +285,17 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Check if the string contains a character
|
/// \brief Check if the string contains a character
|
||||||
/// \param c The character to find
|
/// \param c The character to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns `true` if `c` is contained in `this`
|
/// \returns \f$true\f$ if \f$c\f$ is contained in \f$this\f$
|
||||||
constexpr bool contains(char c, size_t i = 0) const {
|
constexpr bool contains(char c, size_t i = 0) const {
|
||||||
return find(c, i) != size();
|
return find(c, i) != size();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
|
||||||
/// \param c the character to find
|
/// \param c the character to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(char c, size_t i = 0) const {
|
constexpr size_t find(char c, size_t i = 0) const {
|
||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -306,10 +306,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const string& str, size_t i = 0) const { // bounds check
|
constexpr size_t find(const string& str, size_t i = 0) const { // bounds check
|
||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -320,10 +320,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
constexpr size_t find(const cstring& str, size_t i = 0) const {
|
||||||
if (i + str.size() > size()) { // bounds check
|
if (i + str.size() > size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -334,10 +334,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
/// \brief Finds the index of the last occurrence of \f$c\f$ in the string.
|
||||||
/// \param c the string to find
|
/// \param c the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -352,10 +352,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
constexpr size_t rfind(const cstring& str, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -373,10 +373,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -395,9 +395,9 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Retrieve a substring of a string
|
/// \brief Retrieve a substring of a string
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \returns A new string containing the range of characters specified by `i` and `n`
|
/// \returns A new string containing the range of characters specified by \f$i\f$ and \f$n\f$
|
||||||
constexpr _string substring(size_t i, size_t n = npos) const {
|
constexpr _string substring(size_t i, size_t n = npos) const {
|
||||||
if (i >= size() || n == 0) {
|
if (i >= size() || n == 0) {
|
||||||
return _string("");
|
return _string("");
|
||||||
@@ -415,7 +415,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Resize
|
/// \brief String Resize
|
||||||
/// \brief Resizes the underlying allocation to hold `n` characters and a null terminator.
|
/// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator.
|
||||||
/// \param n The new size of the string
|
/// \param n The new size of the string
|
||||||
constexpr void resize(size_t n) {
|
constexpr void resize(size_t n) {
|
||||||
_str.creallocate(n + 1);
|
_str.creallocate(n + 1);
|
||||||
@@ -425,7 +425,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Append
|
/// \brief Character Append
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns A new string containing the previous contents and an additional character `c`.
|
/// \returns A new string containing the previous contents and an additional character \f$c\f$.
|
||||||
constexpr _string operator+(char c) const {
|
constexpr _string operator+(char c) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _string(1, c);
|
return _string(1, c);
|
||||||
@@ -440,7 +440,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Prepend
|
/// \brief Character Prepend
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns A new string containing the character `c` followed by the previous contents.
|
/// \returns A new string containing the character \f$c\f$ followed by the previous contents.
|
||||||
friend constexpr _string operator+(char c, const _string& str) {
|
friend constexpr _string operator+(char c, const _string& str) {
|
||||||
_string res(str.size() + 1);
|
_string res(str.size() + 1);
|
||||||
res[0] = c;
|
res[0] = c;
|
||||||
@@ -450,7 +450,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param cstr The string to append
|
/// \param cstr The string to append
|
||||||
/// \returns A new string containing the previous contents followed by the contents of `cstr`
|
/// \returns A new string containing the previous contents followed by the contents of \f$cstr\f$
|
||||||
constexpr _string operator+(const cstring& cstr) const {
|
constexpr _string operator+(const cstring& cstr) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _string(cstr);
|
return _string(cstr);
|
||||||
@@ -465,7 +465,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Append
|
/// \brief String Append
|
||||||
/// \param str The string to append
|
/// \param str The string to append
|
||||||
/// \returns A new string containing the previous contents followed by the contents of `cstr`
|
/// \returns A new string containing the previous contents followed by the contents of \f$cstr\f$
|
||||||
constexpr _string operator+(const _string& str) const {
|
constexpr _string operator+(const _string& str) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _string(str);
|
return _string(str);
|
||||||
@@ -483,7 +483,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Append Assignment
|
/// \brief Character Append Assignment
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns `this` string containing an additional character `c`.
|
/// \returns \f$this\f$ string containing an additional character \f$c\f$.
|
||||||
constexpr _string& operator+=(char c) {
|
constexpr _string& operator+=(char c) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
_str.callocate(2);
|
_str.callocate(2);
|
||||||
@@ -497,7 +497,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param cstr The string to append
|
/// \param cstr The string to append
|
||||||
/// \returns `this` string expanded to additionally contain `cstr`
|
/// \returns \f$this\f$ string expanded to additionally contain \f$cstr\f$
|
||||||
constexpr _string& operator+=(const cstring& cstr) {
|
constexpr _string& operator+=(const cstring& cstr) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return *this = cstr;
|
return *this = cstr;
|
||||||
@@ -511,7 +511,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Append Assignment
|
/// \brief String Append Assignment
|
||||||
/// \param str The string to append
|
/// \param str The string to append
|
||||||
/// \returns `this` string expanded to additionally contain `str`
|
/// \returns \f$this\f$ string expanded to additionally contain \f$str\f$
|
||||||
constexpr _string& operator+=(const _string& str) {
|
constexpr _string& operator+=(const _string& str) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return *this = str;
|
return *this = str;
|
||||||
|
|||||||
@@ -267,10 +267,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
|
||||||
/// \param c the character to find
|
/// \param c the character to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||||
if (i >= _size) { // bounds check
|
if (i >= _size) { // bounds check
|
||||||
return _size;
|
return _size;
|
||||||
@@ -281,10 +281,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
||||||
if (i + str._size > _size) { // bounds check
|
if (i + str._size > _size) { // bounds check
|
||||||
return _size;
|
return _size;
|
||||||
@@ -295,10 +295,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
/// \brief Finds the index of the last occurrence of \f$c\f$ in the string.
|
||||||
/// \param c the string to find
|
/// \param c the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(char c, size_t i = npos) const {
|
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return _size;
|
return _size;
|
||||||
@@ -312,10 +312,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return _size;
|
return _size;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
/// \brief Sized Constructor, initializes a null-terminated string of size \f$n\f$ with `'c'...`
|
||||||
/// \param n the number of wchar_tacters
|
/// \param n the number of wchar_tacters
|
||||||
/// \param c the wchar_tacter to fill with
|
/// \param c the wchar_tacter to fill with
|
||||||
///
|
///
|
||||||
@@ -78,7 +78,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Alloc Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
/// \brief Sized Alloc Constructor, initializes a null-terminated string of size \f$n\f$ with `'c'...`
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \param c the character to fill with
|
/// \param c the character to fill with
|
||||||
/// \param alloc The allocator to use
|
/// \param alloc The allocator to use
|
||||||
@@ -180,7 +180,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` if the string contains no characters, `false` otherwise.
|
/// \returns \f$true\f$ if the string contains no characters, \f$false\f$ otherwise.
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
/// \param i An offset to start with in `this`
|
/// \param i An offset to start with in \f$this\f$
|
||||||
/// \param n The number of characters to compare
|
/// \param n The number of characters to compare
|
||||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||||
/// current locale, otherwise a positive value.
|
/// current locale, otherwise a positive value.
|
||||||
@@ -247,7 +247,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Comparison
|
/// \brief String Comparison
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \param n The number of characters to compare
|
/// \param n The number of characters to compare
|
||||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||||
/// current locale, otherwise a positive value.
|
/// current locale, otherwise a positive value.
|
||||||
@@ -278,17 +278,17 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Check if the string contains a character
|
/// \brief Check if the string contains a character
|
||||||
/// \param c The character to find
|
/// \param c The character to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns `true` if `c` is contained in `this`
|
/// \returns \f$true\f$ if \f$c\f$ is contained in \f$this\f$
|
||||||
constexpr bool contains(char c, size_t i = 0) const {
|
constexpr bool contains(char c, size_t i = 0) const {
|
||||||
return find(c, i) != size();
|
return find(c, i) != size();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
|
||||||
/// \param c the wchar_tacter to find
|
/// \param c the wchar_tacter to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -299,10 +299,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const _wstring& str, size_t i = 0) const { // bounds check
|
constexpr size_t find(const _wstring& str, size_t i = 0) const { // bounds check
|
||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -313,10 +313,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
constexpr size_t find(const wcstring& str, size_t i = 0) const {
|
||||||
if (i + str.size() > size()) { // bounds check
|
if (i + str.size() > size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
@@ -327,10 +327,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `c` in the string.
|
/// \brief Finds the index of the last occurrence of \f$c\f$ in the string.
|
||||||
/// \param c the string to find
|
/// \param c the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$c\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(wchar_t c, size_t i = npos) const {
|
constexpr size_t rfind(wchar_t c, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -345,10 +345,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
constexpr size_t rfind(const wcstring& str, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -366,10 +366,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `str` in the string.
|
/// \brief Finds the index of the last occurrence of \f$str\f$ in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of \f$str\f$ if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
||||||
if (size() == 0) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
@@ -388,9 +388,9 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Retrieve a substring of a string
|
/// \brief Retrieve a substring of a string
|
||||||
/// \param i An offset to start at in `this`
|
/// \param i An offset to start at in \f$this\f$
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \returns A new string containing the range of characters specified by `i` and `n`
|
/// \returns A new string containing the range of characters specified by \f$i\f$ and \f$n\f$
|
||||||
constexpr _wstring substring(size_t i, size_t n = npos) const {
|
constexpr _wstring substring(size_t i, size_t n = npos) const {
|
||||||
if (i >= size()) {
|
if (i >= size()) {
|
||||||
return _wstring("");
|
return _wstring("");
|
||||||
@@ -408,7 +408,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Resize
|
/// \brief String Resize
|
||||||
/// \brief Resizes the underlying allocation to hold `n` characters and a null terminator.
|
/// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator.
|
||||||
/// \param n The new size of the string
|
/// \param n The new size of the string
|
||||||
constexpr void resize(size_t n) {
|
constexpr void resize(size_t n) {
|
||||||
_str.creallocate(n + 1);
|
_str.creallocate(n + 1);
|
||||||
@@ -418,7 +418,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Append
|
/// \brief Character Append
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns A new string containing the previous contents and an additional character `c`.
|
/// \returns A new string containing the previous contents and an additional character \f$c\f$.
|
||||||
constexpr _wstring operator+(wchar_t c) const {
|
constexpr _wstring operator+(wchar_t c) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _wstring(1, c);
|
return _wstring(1, c);
|
||||||
@@ -433,7 +433,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Prepend
|
/// \brief Character Prepend
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns A new string containing the character `c` followed by the previous contents.
|
/// \returns A new string containing the character \f$c\f$ followed by the previous contents.
|
||||||
friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
|
friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
|
||||||
_wstring res(1, c);
|
_wstring res(1, c);
|
||||||
return res += str;
|
return res += str;
|
||||||
@@ -441,7 +441,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param cstr The string to append
|
/// \param cstr The string to append
|
||||||
/// \returns A new string containing the previous contents followed by the contents of `cstr`
|
/// \returns A new string containing the previous contents followed by the contents of \f$cstr\f$
|
||||||
constexpr _wstring operator+(const wcstring& cstr) const {
|
constexpr _wstring operator+(const wcstring& cstr) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _wstring(cstr);
|
return _wstring(cstr);
|
||||||
@@ -456,7 +456,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Append
|
/// \brief String Append
|
||||||
/// \param str The string to append
|
/// \param str The string to append
|
||||||
/// \returns A new string containing the previous contents followed by the contents of `cstr`
|
/// \returns A new string containing the previous contents followed by the contents of \f$cstr\f$
|
||||||
constexpr _wstring operator+(const _wstring& str) const {
|
constexpr _wstring operator+(const _wstring& str) const {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return _wstring(str);
|
return _wstring(str);
|
||||||
@@ -474,7 +474,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Character Append Assignment
|
/// \brief Character Append Assignment
|
||||||
/// \param c A character to append
|
/// \param c A character to append
|
||||||
/// \returns `this` string containing an additional character `c`.
|
/// \returns \f$this\f$ string containing an additional character \f$c\f$.
|
||||||
constexpr _wstring& operator+=(wchar_t c) {
|
constexpr _wstring& operator+=(wchar_t c) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
_str.callocate(2);
|
_str.callocate(2);
|
||||||
@@ -488,7 +488,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \param cstr The string to append
|
/// \param cstr The string to append
|
||||||
/// \returns `this` string expanded to additionally contain `cstr`
|
/// \returns \f$this\f$ string expanded to additionally contain \f$cstr\f$
|
||||||
constexpr _wstring& operator+=(const wcstring& cstr) {
|
constexpr _wstring& operator+=(const wcstring& cstr) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return *this = cstr;
|
return *this = cstr;
|
||||||
@@ -502,7 +502,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief String Append Assignment
|
/// \brief String Append Assignment
|
||||||
/// \param str The string to append
|
/// \param str The string to append
|
||||||
/// \returns `this` string expanded to additionally contain `str`
|
/// \returns \f$this\f$ string expanded to additionally contain \f$str\f$
|
||||||
constexpr _wstring& operator+=(const _wstring& str) {
|
constexpr _wstring& operator+=(const _wstring& str) {
|
||||||
if (_str == nullptr) {
|
if (_str == nullptr) {
|
||||||
return *this = str;
|
return *this = str;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Default Constructor
|
/// \brief Default Constructor
|
||||||
///
|
///
|
||||||
/// \details Initializes the held atomic variable with `0`.
|
/// \details Initializes the held atomic variable with \f$0\f$.
|
||||||
constexpr atomic() noexcept
|
constexpr atomic() noexcept
|
||||||
: _value(static_cast<T>(0)) {
|
: _value(static_cast<T>(0)) {
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Value Constructor
|
/// \brief Value Constructor
|
||||||
///
|
///
|
||||||
/// \details Initializes the held atomic variable with `value`.
|
/// \details Initializes the held atomic variable with \f$value\f$.
|
||||||
/// \param value The value to initialize the atomic variable with.
|
/// \param value The value to initialize the atomic variable with.
|
||||||
constexpr atomic(const T value) noexcept
|
constexpr atomic(const T value) noexcept
|
||||||
: _value(value) {
|
: _value(value) {
|
||||||
@@ -95,9 +95,9 @@ public:
|
|||||||
atomic& operator=(const atomic&) volatile = delete;
|
atomic& operator=(const atomic&) volatile = delete;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically assigns `x` to the atomic variable.
|
/// \details Atomically assigns \f$x\f$ to the atomic variable.
|
||||||
/// \param x The value to assign
|
/// \param x The value to assign
|
||||||
/// \returns `x`
|
/// \returns \f$x\f$
|
||||||
T operator=(const T x) noexcept {
|
T operator=(const T x) noexcept {
|
||||||
this->store(x);
|
this->store(x);
|
||||||
return x;
|
return x;
|
||||||
@@ -106,9 +106,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Stores a value into an atomic object
|
/// \brief Stores a value into an atomic object
|
||||||
///
|
///
|
||||||
/// \details Atomically assigns `x` to the atomic variable.
|
/// \details Atomically assigns \f$x\f$ to the atomic variable.
|
||||||
/// \param x The value to assign
|
/// \param x The value to assign
|
||||||
/// \returns `x`
|
/// \returns \f$x\f$
|
||||||
T operator=(const T x) volatile noexcept {
|
T operator=(const T x) volatile noexcept {
|
||||||
this->store(x);
|
this->store(x);
|
||||||
return x;
|
return x;
|
||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
// Modifiers ===========================================================================================================
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically replaces the current value with `x`. Memory is affected according to the value of `order`.
|
/// \details Atomically replaces the current value with \f$x\f$. Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param x The value to store into the atomic variable
|
/// \param x The value to store into the atomic variable
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
void store(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
void store(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Atomically replaces the value of the atomic object with a non-atomic argument
|
/// \brief Atomically replaces the value of the atomic object with a non-atomic argument
|
||||||
///
|
///
|
||||||
/// \details Atomically replaces the current value with `x`. Memory is affected according to the value of `order`.
|
/// \details Atomically replaces the current value with \f$x\f$. Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param x The value to store into the atomic variable
|
/// \param x The value to store into the atomic variable
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
void store(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
void store(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
@@ -139,7 +139,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically loads and returns the current value of the atomic variable.
|
/// \details Atomically loads and returns the current value of the atomic variable.
|
||||||
/// Memory is affected according to the value of `order`.
|
/// Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
/// \returns The current value of the atomic variable.
|
/// \returns The current value of the atomic variable.
|
||||||
T load(memory_order order = memory_order_seq_cst) const noexcept {
|
T load(memory_order order = memory_order_seq_cst) const noexcept {
|
||||||
@@ -150,7 +150,7 @@ public:
|
|||||||
/// \brief Atomically obtains the value of the atomic object
|
/// \brief Atomically obtains the value of the atomic object
|
||||||
///
|
///
|
||||||
/// \details Atomically loads and returns the current value of the atomic variable.
|
/// \details Atomically loads and returns the current value of the atomic variable.
|
||||||
/// Memory is affected according to the value of `order`.
|
/// Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
/// \returns The current value of the atomic variable.
|
/// \returns The current value of the atomic variable.
|
||||||
T load(memory_order order = memory_order_seq_cst) const volatile noexcept {
|
T load(memory_order order = memory_order_seq_cst) const volatile noexcept {
|
||||||
@@ -174,8 +174,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically replaces the underlying value with `x` (a read-modify-write operation).
|
/// \details Atomically replaces the underlying value with \f$x\f$ (a read-modify-write operation).
|
||||||
/// Memory is affected according to the value of `order`.
|
/// Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param x Value to assign
|
/// \param x Value to assign
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
/// \return The value of the atomic variable before the call.
|
/// \return The value of the atomic variable before the call.
|
||||||
@@ -186,8 +186,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Atomically replaces the value of the atomic object and obtains the value held previously
|
/// \brief Atomically replaces the value of the atomic object and obtains the value held previously
|
||||||
///
|
///
|
||||||
/// \details Atomically replaces the underlying value with `x` (a read-modify-write operation).
|
/// \details Atomically replaces the underlying value with \f$x\f$ (a read-modify-write operation).
|
||||||
/// Memory is affected according to the value of `order`.
|
/// Memory is affected according to the value of \f$order\f$.
|
||||||
/// \param x Value to assign
|
/// \param x Value to assign
|
||||||
/// \param order Memory order constraints to enforce
|
/// \param order Memory order constraints to enforce
|
||||||
/// \return The value of the atomic variable before the call.
|
/// \return The value of the atomic variable before the call.
|
||||||
@@ -197,39 +197,39 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
||||||
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
||||||
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param order The memory synchronization ordering for both operations.
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
||||||
}
|
}
|
||||||
@@ -237,52 +237,52 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param order The memory synchronization ordering for both operations.
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
||||||
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
||||||
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param order The memory synchronization ordering for both operations.
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
||||||
}
|
}
|
||||||
@@ -290,13 +290,13 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
||||||
///
|
///
|
||||||
/// \details Atomically compares the value of `*this` with that of `exp`.
|
/// \details Atomically compares the value of `*this` with that of \f$exp\f$.
|
||||||
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
/// If they are equal, replaces the former with \f$x\f$ (performs read-modify-write operation).
|
||||||
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
/// Otherwise, loads the actual value stored in *this into \f$exp\f$ (performs load operation).
|
||||||
/// \param exp Reference to the value expected to be found in the atomic object.
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
/// \param x The value to store in the atomic object if it is as expected.
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
/// \param order The memory synchronization ordering for both operations.
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
/// \returns \f$true\f$ if the underlying atomic value was successfully changed, \f$false\f$ otherwise.
|
||||||
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,16 +36,16 @@ namespace fennec
|
|||||||
|
|
||||||
scene_node* scene::operator[](const cstring& name) const {
|
scene_node* scene::operator[](const cstring& name) const {
|
||||||
list<size_t> parse;
|
list<size_t> parse;
|
||||||
parse.push_back(root);
|
parse.push_back(table_t::root);
|
||||||
while (not parse.empty()) {
|
while (not parse.empty()) {
|
||||||
size_t n = parse.front();
|
size_t n = parse.front();
|
||||||
if (_table[n].value->name == name) {
|
if (_table[n]->name == name) {
|
||||||
return _table[n].value;
|
return _table[n].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-Order traversal
|
// Pre-Order traversal
|
||||||
parse.push_front(next(n));
|
parse.push_front(_table.next(n));
|
||||||
parse.push_front(child(n));
|
parse.push_front(_table.child(n));
|
||||||
parse.pop_front();
|
parse.pop_front();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -53,16 +53,16 @@ scene_node* scene::operator[](const cstring& name) const {
|
|||||||
|
|
||||||
scene_node* scene::operator[](const string& name) const {
|
scene_node* scene::operator[](const string& name) const {
|
||||||
list<size_t> parse;
|
list<size_t> parse;
|
||||||
parse.push_back(root);
|
parse.push_back(table_t::root);
|
||||||
while (not parse.empty()) {
|
while (not parse.empty()) {
|
||||||
size_t n = parse.front();
|
size_t n = parse.front();
|
||||||
if (_table[n].value->name == name) {
|
if (_table[n]->name == name) {
|
||||||
return _table[n].value;
|
return _table[n].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-Order traversal
|
// Pre-Order traversal
|
||||||
parse.push_front(next(n));
|
parse.push_front(_table.next(n));
|
||||||
parse.push_front(child(n));
|
parse.push_front(_table.child(n));
|
||||||
parse.pop_front();
|
parse.pop_front();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user