aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/kstd/kstd/asm_ptr.hpp8
-rw-r--r--libs/kstd/kstd/bits/shared_ptr.hpp297
-rw-r--r--libs/kstd/kstd/bits/unique_ptr.hpp202
-rw-r--r--libs/kstd/kstd/os/error.hpp32
-rw-r--r--libs/kstd/kstd/stack.hpp183
-rw-r--r--libs/kstd/kstd/string.hpp11
6 files changed, 294 insertions, 439 deletions
diff --git a/libs/kstd/kstd/asm_ptr.hpp b/libs/kstd/kstd/asm_ptr.hpp
index c06a8b52..5ffc480f 100644
--- a/libs/kstd/kstd/asm_ptr.hpp
+++ b/libs/kstd/kstd/asm_ptr.hpp
@@ -7,11 +7,9 @@
namespace kstd
{
- /**
- * @brief A pointer that is defined in some assembly source file.
- *
- * @tparam Type The type of the pointer
- */
+ //! A pointer that is defined in some assembly source file.
+ //!
+ //! @tparam Type The type of the pointer
template<typename Type>
struct asm_ptr
{
diff --git a/libs/kstd/kstd/bits/shared_ptr.hpp b/libs/kstd/kstd/bits/shared_ptr.hpp
index 638fccf3..c3367967 100644
--- a/libs/kstd/kstd/bits/shared_ptr.hpp
+++ b/libs/kstd/kstd/bits/shared_ptr.hpp
@@ -1,6 +1,8 @@
#ifndef KSTD_BITS_SHARED_PTR_HPP
#define KSTD_BITS_SHARED_PTR_HPP
+// IWYU pragma: private, include <kstd/memory.hpp>
+
#include <array>
#include <atomic>
#include <compare>
@@ -10,8 +12,6 @@
#include <type_traits>
#include <utility>
-// IWYU pragma: private, include <kstd/memory.hpp>
-
namespace kstd
{
@@ -381,13 +381,9 @@ namespace kstd
template<typename T>
weak_ptr(shared_ptr<T>) -> weak_ptr<T>;
- /**
- * @brief enable_shared_from_this is a base class that allows an object that is currently managed by a shared_ptr to
- * create additional shared_ptr instances that share ownership of the same object. This is usefl when you want to
- * create shared_ptr instances in a member function of the object.
- *
- * @tparam T The type of the managed object.
- */
+ //! A base class allowing an object that is currently managed by a shared_ptr to create additional such pointers.
+ //!
+ //! @tparam T The type of the managed object.
template<typename T>
struct enable_shared_from_this
{
@@ -397,17 +393,13 @@ namespace kstd
friend T;
public:
- /**
- * @brief Returns a shared_ptr that shares ownership of *this.
- */
+ //! Create a new shared_ptr sharing ownership of *this.
auto shared_from_this() -> shared_ptr<T>
{
return shared_ptr<T>(m_weak_this);
}
- /**
- * @brief Returns a shared_ptr that shares ownership of *this.
- */
+ //! Create a new shared_ptr sharing ownership of *this.
auto shared_from_this() const -> shared_ptr<T const>
{
return shared_ptr<T const>(m_weak_this);
@@ -430,21 +422,13 @@ namespace kstd
m_weak_this = ptr;
}
- mutable weak_ptr<T> m_weak_this{}; ///< Weak pointer to the object, used for shared_from_this functionality.
+ //! Weak pointer to the object, used for shared_from_this functionality.
+ mutable weak_ptr<T> m_weak_this{};
};
- /**
- * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several
- * shared_ptr objects may own the same object. The object is destroyed and its memory deallocated when either of
- * the following happens: the last remaining shared_ptr owning the object is destroyed; the last remaining
- * shared_ptr owning the object is assigned another pointer via operator= or reset(). A
- * shared_ptr can share ownership of an object while storing a pointer to another object. This feature can be used
- * to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(),
- * the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count
- * reaches zero.
- *
- * @tparam T The type of the managed object.
- */
+ //! A shared-ownership smart pointer.
+ //!
+ //! @tparam T The type of the managed object.
template<typename T>
struct shared_ptr
{
@@ -461,27 +445,21 @@ namespace kstd
using element_type = std::remove_extent_t<T>;
using weak_type = weak_ptr<T>;
- /**
- * @brief Construct an empty shared_ptr.
- */
+ //! Construct an empty shared pointer.
constexpr shared_ptr() noexcept
: m_pointer(nullptr)
, m_control_block(nullptr)
{}
- /**
- * @brief Construct an empty shared_ptr from nullptr.
- */
+ //! @brief Construct an empty shared pointer.
constexpr shared_ptr(std::nullptr_t) noexcept
: m_pointer(nullptr)
, m_control_block(nullptr)
{}
- /**
- * @brief Constructor.
- *
- * @param pointer A pointer to an object to manage (default is nullptr).
- */
+ //! Construct a new shared pointer managing the given object.
+ //!
+ //! @param pointer A pointer to an object to manage.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
constexpr explicit shared_ptr(U * pointer)
@@ -505,12 +483,10 @@ namespace kstd
assign_enable_shared_from_this(pointer);
}
- /**
- * @brief Construct a shared_ptr from a weak_ptr. If other is not expired, constructs a shared_ptr which shares
- * ownership of the object managed by other. Otherwise, constructs an empty shared_ptr.
- *
- * @param other The weak_ptr to construct from.
- */
+ //! @brief Construct a shared_ptr from a weak_ptr. If other is not expired, constructs a shared_ptr which shares
+ //! ownership of the object managed by other. Otherwise, constructs an empty shared_ptr.
+ //!
+ //! @param other The weak_ptr to construct from.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
explicit shared_ptr(weak_ptr<U> const & other)
@@ -540,11 +516,9 @@ namespace kstd
}
}
- /**
- * @brief Copy constructor.
- *
- * @param other The shared_ptr to copy from.
- */
+ //! Create a new shared pointer by sharing ownership with an existing one.
+ //!
+ //! @param other The shared_ptr to copy from.
shared_ptr(shared_ptr const & other) noexcept
: m_pointer(other.m_pointer)
, m_control_block(other.m_control_block)
@@ -555,12 +529,10 @@ namespace kstd
}
}
- /**
- * @brief Converting copy constructor for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other The shared_ptr to copy from.
- */
+ //! Create a new shared pointer by sharing ownership with a compatible one.
+ //!
+ //! @tparam U Source pointer element type.
+ //! @param other The shared_ptr to copy from.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
shared_ptr(shared_ptr<U> const & other) noexcept
@@ -573,22 +545,18 @@ namespace kstd
}
}
- /**
- * @brief Move constructor.
- *
- * @param other The shared_ptr to move from.
- */
+ //! Create a new shared pointer by moving from an existing one.
+ //!
+ //! @param other The shared_ptr to move from.
shared_ptr(shared_ptr && other) noexcept
: m_pointer(std::exchange(other.m_pointer, nullptr))
, m_control_block(std::exchange(other.m_control_block, nullptr))
{}
- /**
- * @brief Converting move constructor for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other The shared_ptr to move from.
- */
+ //! Create a new shared pointer by moving from a compatible one.
+ //!
+ //! @tparam U Source pointer element type.
+ //! @param other The shared pointer to move from.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
shared_ptr(shared_ptr<U> && other) noexcept
@@ -596,27 +564,24 @@ namespace kstd
, m_control_block(std::exchange(other.m_control_block, nullptr))
{}
- /**
- * @brief Copy assignment operator. Replaces the managed object with the one managed by r. Shares ownership of the
- * object managed by r. If r manages no object, *this manages no object too. Equivalent to
- * shared_ptr<T>(r).swap(*this).
- *
- * @param other Another smart pointer to share the ownership with.
- * @return Reference to this shared pointer.
- */
+ //! Replace the managed object with the one managed by another shared pointer.
+ //!
+ //! Afterwards, this pointer shares ownership of the object managed by @p other. If @p other manages no object,
+ //! this pointer manages no object either. Equivalent to @c shared_ptr<T>(other).swap(*this).
+ //!
+ //! @param other The shared pointer to share the ownership with.
+ //! @return a reference to this shared pointer.
auto operator=(shared_ptr const & other) -> shared_ptr &
{
shared_ptr<T>(other).swap(*this);
return *this;
}
- /**
- * @brief Converting copy assignment for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other Another smart pointer to share ownership with.
- * @return Reference to this shared pointer.
- */
+ //! Replace the managed object with the one managed by a compatible shared pointer.
+ //!
+ //! @tparam U Source pointer element type.
+ //! @param other The shared pointer to share ownership with.
+ //! @return a reference to this shared pointer.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
auto operator=(shared_ptr<U> const & other) -> shared_ptr &
@@ -625,26 +590,24 @@ namespace kstd
return *this;
}
- /**
- * @brief Move assignment operator. Move-assigns a shared_ptr from r. After the assignment, *this contains a copy of
- * the previous state of r, and r is empty. Equivalent to shared_ptr<T>(std::move(r)).swap(*this).
- *
- * @param other Another smart pointer to acquire the ownership from.
- * @return Reference to this shared pointer.
- */
+ //! Replace the managed object with the one managed by another shared pointer.
+ //!
+ //! Afterwards, this pointer contains the previous state of @p other, and @p other manages no object. Equivalent to
+ //! shared_ptr<T>(std::move(other)).swap(*this).
+ //!
+ //! @param other The shared pointer to acquire the ownership from.
+ //! @return Reference to this shared pointer.
auto operator=(shared_ptr && other) noexcept -> shared_ptr &
{
shared_ptr<T>(std::move(other)).swap(*this);
return *this;
}
- /**
- * @brief Converting move assignment for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other Another smart pointer to acquire ownership from.
- * @return Reference to this shared pointer.
- */
+ //! Replace the managed object with the one managed by a compatible shared pointer.
+ //!
+ //! @tparam U Source pointer element type.
+ //! @param other The shared pointer to acquire ownership from.
+ //! @return Reference to this shared pointer.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
auto operator=(shared_ptr<U> && other) noexcept -> shared_ptr &
@@ -653,9 +616,9 @@ namespace kstd
return *this;
}
- /**
- * @brief Reset this shared_ptr to empty via nullptr assignment.
- */
+ //! Reset this shared pointer to manage no object.
+ //!
+ //! @return A reference to this shared_ptr.
auto operator=(std::nullptr_t) noexcept -> shared_ptr &
{
cleanup();
@@ -664,9 +627,7 @@ namespace kstd
return *this;
}
- /**
- * @brief Destructor. Cleans up resources if necessary.
- */
+ //! Destroy this shared pointer, potentially destroying the managed object.
~shared_ptr()
{
cleanup();
@@ -708,33 +669,28 @@ namespace kstd
return std::compare_three_way{}(lhs.get(), static_cast<shared_ptr::element_type *>(nullptr));
}
- /**
- * @brief Replaces the managed object.
- *
- * @param ptr Pointer to a new object to manage (default = nullptr).
- */
+ //! Replace the managed object.
+ //!
+ //! @param ptr Pointer to a new object to manage.
void reset(T * ptr = nullptr)
{
shared_ptr<T>(ptr).swap(*this);
}
- /**
- * @brief Exchanges the stored pointer values and the ownerships of *this and r. Reference counts, if any, are not
- * adjusted.
- *
- * @param other The shared_ptr to swap with.
- */
- void swap(shared_ptr & other)
+ //! Exchange ownership of the object manages by this shared pointer and another one.
+ //!
+ //! @param other The shared pointer to swap ownership with.
+ void swap(shared_ptr & other) noexcept
{
std::ranges::swap(m_pointer, other.m_pointer);
std::ranges::swap(m_control_block, other.m_control_block);
}
- /**
- * @brief Dereference operator. If get() is a null pointer, the behavior is undefined.
- *
- * @return Returns the object owned by *this, equivalent to *get().
- */
+ //! Access the object managed by this shared pointer.
+ //!
+ //! @warning If this shared pointer does not manage an object, the behavior is undefined.
+ //!
+ //! @return The object manages by this shared pointer.
template<typename U = T>
requires(!std::is_void_v<std::remove_cv<U>>)
[[nodiscard]] auto operator*() const -> U &
@@ -742,37 +698,33 @@ namespace kstd
return *m_pointer;
}
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
+ //! Access a member of the managed object.
+ //!
+ //! @warning If this shared pointer does not manage an object, the behavior is undefined.
+ //!
+ //! @return A pointer to the managed object.
[[nodiscard]] auto operator->() const -> T *
{
return m_pointer;
}
- /**
- * @brief Returns a pointer to the managed object or nullptr if no object is owned.
- *
- * @return Pointer to the managed object or nullptr if no object is owned.
- */
+ //! Get the stored pointer.
+ //!
+ //! @return The stored pointer.
[[nodiscard]] auto get() const -> T *
{
return m_pointer;
}
- /**
- * @brief Returns the number of different shared_ptr instances (*this included) managing the current object. If
- * there is no managed object, ​0​ is returned.
- *
- * @note Common use cases include comparison with ​0​. If use_count returns zero, the shared pointer is empty
- * and manages no objects (whether or not its stored pointer is nullptr). Comparison with 1. If use_count returns 1,
- * there are no other owners.
- *
- * @return The number of Shared_pointer instances managing the current object or ​0​ if there is no managed
- * object.
- */
+ //! Get the number of shared references to the object managed by this shared pointer.
+ //!
+ //! Common use cases include comparison with 0. If use_count returns zero, the shared pointer is empty and manages
+ //! no objects (whether or not its stored pointer is nullptr). If use_count returns 1, there are no other owners.
+ //!
+ //! @note This function is inherently racy. Another thread, constructing or destroying a shared pointer sharing
+ //! managing the same object may change the value returned by use_count().
+ //!
+ //! @return The number of shared references to the currently managed object, or 0 if no such object exists.
[[nodiscard]] auto use_count() const -> std::size_t
{
if (m_control_block != nullptr)
@@ -783,16 +735,22 @@ namespace kstd
return 0;
}
- /**
- * @brief Checks whether *this owns an object, i.e. whether get() != nullptr.
- *
- * @return true if *this owns an object, false otherwise.
- */
+ //! Check if this shared pointer owns an object.
+ //!
+ //! @return @c true if this shared pointer owns an object, @c false otherwise.
[[nodiscard]] explicit operator bool() const
{
return m_pointer != nullptr;
}
+ //! Swap the contents of two shared pointers
+ //!
+ //! @param lhs, rhs Shared pointers whose contents to swap.
+ auto friend swap(shared_ptr & lhs, shared_ptr & rhs) noexcept -> void
+ {
+ lhs.swap(rhs);
+ }
+
private:
shared_ptr(T * pointer, bits::shared_ptr_control_block_base * control_block, bits::weak_ptr_locked_t) noexcept
: m_pointer(pointer)
@@ -806,14 +764,10 @@ namespace kstd
assign_enable_shared_from_this(pointer);
}
- /**
- * @brief If the candidate type inherits from enable_shared_from_this, assigns the internal weak pointer to this
- * shared_ptr. This weak_ptr is used to implement shared_from_this functionality for the candidate type. If the
- * candidate type does not inherit from enable_shared_from_this, this function does nothing.
- *
- * @tparam U The candidate type to check for enable_shared_from_this inheritance.
- * @param candidate The candidate object to assign the internal weak pointer for.
- */
+ //! Assign the internal weak pointer of the managed object, it its type derives shared_from_this.
+ //!
+ //! @tparam U The candidate type to check for enable_shared_from_this inheritance.
+ //! @param candidate The candidate object to assign the internal weak pointer for.
template<typename U>
auto assign_enable_shared_from_this(U * candidate) -> void
{
@@ -826,9 +780,9 @@ namespace kstd
}
}
- /**
- * @brief Releases ownership and deletes the object if this was the last reference to the owned managed object.
- */
+ //! Release ownership of the managed object
+ //!
+ //! If this is the last reference to the object, the object will be deleted.
auto cleanup() -> void
{
if (m_control_block != nullptr)
@@ -843,28 +797,15 @@ namespace kstd
bits::shared_ptr_control_block_base * m_control_block; ///< Shared control block.
};
- /**
- * Swap the contents of lhs and rhs.
- *
- * @tparam T Type of the managed object.
- * @param lhs, rhs Shared pointers whose contents to swap.
- */
- template<typename T>
- auto swap(shared_ptr<T> & lhs, shared_ptr<T> & rhs) -> void
- {
- lhs.swap(rhs);
- }
-
- /**
- * @brief Constructs an object of type T and wraps it in a shared_ptr. Constructs a non-array type T. The
- * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is
- * not an array type.
- *
- * @tparam T Type of the managed object.
- * @tparam Args Argument types for T's constructor.
- * @param args List of arguments with which an instance of T will be constructed.
- * @returns Shared_pointer of an instance of type T.
- */
+ //! Constructs a new shared pointer managing an object constructed with the given arguments.
+ //!
+ //! @note This function is more efficient than creating an object with operator new and wrapping it with a shared
+ //! pointer, since it only performs one allocation instead of two.
+ //!
+ //! @tparam T Type of the managed object.
+ //! @tparam Args Argument types for T's constructor.
+ //! @param args The arguments to forward to T's constructor.
+ //! @returns A shared pointer that owns the newly created object.
template<typename T, typename... Args>
[[nodiscard]] auto make_shared(Args &&... args) -> shared_ptr<T>
{
diff --git a/libs/kstd/kstd/bits/unique_ptr.hpp b/libs/kstd/kstd/bits/unique_ptr.hpp
index 1df18cf2..89c34c3b 100644
--- a/libs/kstd/kstd/bits/unique_ptr.hpp
+++ b/libs/kstd/kstd/bits/unique_ptr.hpp
@@ -1,194 +1,162 @@
#ifndef KSTD_BITS_UNIQUE_POINTER_HPP
#define KSTD_BITS_UNIQUE_POINTER_HPP
+#include <memory>
#include <utility>
// IWYU pragma: private, include <kstd/memory.hpp>
namespace kstd
{
- /**
- * @brief Unique_pointer is a smart pointer that owns (is responsible for) and manages another object via a pointer
- * and subsequently disposes of that object when the unique_ptr goes out of scope.
- *
- * @tparam T Type of the managed object.
- */
+ //! A single-owner smart pointer.
+ //!
+ //! @tparam T Type of the owned object.
template<typename T>
struct unique_ptr
{
template<typename U>
friend struct unique_ptr;
- /**
- * @brief Constructor.
- *
- * @param ptr A pointer to an object to manage (default is nullptr).
- */
+ //! Construct a new unique pointer, own the given object.
+ //!
+ //! @param ptr A pointer to an object to own.
explicit unique_ptr(T * ptr = nullptr)
- : pointer(ptr)
+ : m_pointer(ptr)
{
// Nothing to do.
}
- /**
- * @brief Destructor that deletes the managed object.
- */
+ //! Destroy the own object.
~unique_ptr()
{
- delete pointer;
+ reset();
}
- /**
- * @brief Deleted copy constructor to enforce unique ownership.
- */
+ //! Deleted copy constructor to enforce unique ownership.
unique_ptr(unique_ptr const &) = delete;
+ //! Create a new unique pointer, transfering ownership from another one.
+ //!
+ //! @param other The unique pointer to transfer ownership from.
+ unique_ptr(unique_ptr && other) noexcept
+ : m_pointer{std::exchange(other.m_pointer, nullptr)}
+ {}
+
+ //! Create a new unique pointer, transfering ownership from a compatible one.
+ //!
+ //! @tparam U The type of the object referenced by the other unique pointer.
+ //! @param other The unique pointer to transfer ownership from.
template<typename U>
requires(std::is_convertible_v<U *, T *>)
unique_ptr(unique_ptr<U> && other) noexcept
- : pointer{std::exchange(other.pointer, nullptr)}
+ : m_pointer{std::exchange(other.m_pointer, nullptr)}
{}
- /**
- * @brief Deleted copy assignment operator to enforce unique ownership.
- */
+ //! Deleted copy assignment operator to enforce unique ownership.
auto operator=(unique_ptr const &) -> unique_ptr & = delete;
- /**
- * @brief Move constructor.
- *
- * @param other Unique pointer to move from.
- */
- unique_ptr(unique_ptr && other) noexcept
- : pointer{std::exchange(other.pointer, nullptr)}
- {}
-
- /**
- * @brief Move assignment operator. Transfers ownership from other to *this as if by calling reset(r.release()).
- *
- * @param other Smart pointer from which ownership will be transferred.
- * @return Reference to this unique pointer.
- */
+ //! Transfers ownership from another unique pointer to this one.
+ //!
+ //! @param other The unique pointer to transfer ownership from.
+ //! @return A reference to this unique pointer.
auto operator=(unique_ptr && other) noexcept -> unique_ptr &
{
if (this != &other)
{
- delete pointer;
- pointer = std::exchange(other.pointer, nullptr);
+ delete m_pointer;
+ m_pointer = std::exchange(other.m_pointer, nullptr);
}
return *this;
}
- /**
- * @brief Dereference operator. If get() is a null pointer, the behavior is undefined.
- *
- * @return Returns the object owned by *this, equivalent to *get().
- */
+ //! Access the object own by this unique pointer.
+ //!
+ //! @warning If this unique pointer does not own an object, the behavior is undefined.
+ //!
+ //! @return The object owned by this.
auto operator*() const -> T &
{
- return *pointer;
+ return *m_pointer;
}
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
+ //! Access a member of the owned object.
+ //!
+ //! @warning If this unique pointer does not own an object, the behavior is undefined.
+ //!
+ //! @return A pointer to the owned object.
auto operator->() const -> T *
{
- return pointer;
+ return m_pointer;
}
- /**
- * @brief Returns a pointer to the managed object or nullptr if no object is owned.
- *
- * @return Pointer to the managed object or nullptr if no object is owned.
- */
+ //! Get a pointer to the object owned by this unique pointer.
+ //!
+ //! @return Pointer to the owned object or nullptr if this unique pointer does not own an object.
[[nodiscard]] auto get() const -> T *
{
- return pointer;
+ return m_pointer;
}
- /**
- * @brief Checks whether *this owns an object, i.e. whether get() != nullptr.
- *
- * @return true if *this owns an object, false otherwise.
- */
+ //! Check if this unique pointer owns an object.
+ //!
+ //! @return @c true if this unique pointer owns an object, @c false otherwise.
explicit operator bool() const noexcept
{
- return pointer != nullptr;
+ return m_pointer != nullptr;
}
- /**
- * @brief Releases the ownership of the managed object, if any.
- * get() returns nullptr after the call.
- * The caller is responsible for cleaning up the object (e.g. by use of get_deleter()).
- *
- * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be
- * returned by get() before the call.
- */
+ //! Release ownership of the owned object, if any.
+ //!
+ //! @warning The caller is responsible for cleaning up the object (e.g. by use of get_deleter()).
+ //!
+ //! @return A pointer to the previously owned object, nullptr if this unique pointer does not own an object.
auto release() -> T *
{
- return std::exchange(pointer, nullptr);
+ return std::exchange(m_pointer, nullptr);
}
- /**
- * @brief Replaces the managed object.
- *
- * @note A test for self-reset, i.e. whether ptr points to an object already managed by *this, is not performed,
- * except where provided as a compiler extension or as a debugging assert. Note that code such as
- * p.reset(p.release()) does not involve self-reset, only code like p.reset(p.get()) does.
- *
- * @param ptr Pointer to a new object to manage (default = nullptr).
- */
+ //! Replace the owned object.
+ //!
+ //! @param ptr The object to own or nullptr if this unique pointer should not own an object.
auto reset(T * ptr = nullptr) -> void
{
- delete std::exchange(pointer, ptr);
+ if (m_pointer)
+ {
+ std::default_delete<T>{}(std::exchange(m_pointer, ptr));
+ }
}
- /**
- * @brief Swaps the managed objects and associated deleters of *this and another unique_ptr object other.
- *
- * @param other Another unique_ptr object to swap the managed object and the deleter with.
- */
+ //! Exchange the owned object with the one owned by another unique pointer.
+ //!
+ //! @param other The unique pointer to exchange ownership with.
auto swap(unique_ptr & other) -> void
{
using std::swap;
- swap(pointer, other.pointer);
+ swap(m_pointer, other.m_pointer);
}
- /**
- * @brief Defaulted three-way comparator operator.
- */
- auto operator<=>(unique_ptr const & other) const = default;
+ //! Exchange the owned objects of two unique pointers.
+ //!
+ //! @param lhs The left hand side of the exchange.
+ //! @param rhs The right hand side of the exchange.
+ auto friend swap(unique_ptr & lhs, unique_ptr & rhs) -> void
+ {
+ lhs.swap(rhs);
+ }
+
+ auto operator<=>(unique_ptr const & other) const noexcept = default;
private:
- T * pointer; ///< The managed pointer.
+ //! The pointer to the owned object.
+ T * m_pointer;
};
- /**
- * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls
- * lhs.swap(rhs).
- *
- * @tparam T Type of the managed object.
- * @param lhs, rhs Smart pointers whose contents to swap.
- */
- template<typename T>
- auto swap(unique_ptr<T> & lhs, unique_ptr<T> & rhs) -> void
- {
- lhs.swap(rhs);
- }
-
- /**
- * @brief Constructs an object of type T and wraps it in a unique_ptr. Constructs a non-array type T. The
- * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is
- * not an array type. The function is equivalent to: unique_ptr<T>(new T(std::forward<Args>(args)...)).
- *
- * @tparam T Type of the managed object.
- * @tparam Args Argument types for T's constructor.
- * @param args List of arguments with which an instance of T will be constructed.
- * @returns Unique_pointer of an instance of type T.
- */
+ //! Construct a new unique pointer by creating a new object.
+ //!
+ //! @tparam T Type of the managed object.
+ //! @tparam Args Argument types for @p T's constructor.
+ //! @param args List of arguments with which an instance of @p T will be constructed.
+ //! @returns a new unique pointer owning an object of type @p T
template<typename T, typename... Args>
auto make_unique(Args &&... args) -> unique_ptr<T>
{
diff --git a/libs/kstd/kstd/os/error.hpp b/libs/kstd/kstd/os/error.hpp
index 9d43fb14..e43ae722 100644
--- a/libs/kstd/kstd/os/error.hpp
+++ b/libs/kstd/kstd/os/error.hpp
@@ -6,27 +6,23 @@
namespace kstd::os
{
- /**
- * @brief Handle an unrecoverable library error.
- *
- * The operating system kernel may choose to implement this function in order to try to perform additional cleanup
- * before terminating execution. If the kernel does not implement this function, the default implementation will be
- * chosen. This default implementation doest nothing.
- */
+ //! Handle an unrecoverable library error.
+ //!
+ //! The operating system kernel may choose to implement this function in order to try to perform additional cleanup
+ //! before terminating execution. If the kernel does not implement this function, the default implementation will be
+ //! chosen. This default implementation doest nothing.
[[noreturn]]
auto abort() -> void;
- /**
- * @brief Terminate execution of the operating system.
- *
- * The operating system must implement this function. This function must terminate the execution of the operating
- * system kernel as is. It may choose to restart the kernel or to halt execution entirely. The implementation must
- * guarantee that execution never return from this function.
- *
- * @param message A message describing the reason for termination of execution.
- * @param where The source code location at which the panic was triggered. In general, no argument shall be provided
- * for this parameter, thus implicitly capturing the location at which the call originates.
- */
+ //! @brief Terminate execution of the operating system.
+ //!
+ //! The operating system must implement this function. This function must terminate the execution of the operating
+ //! system kernel as is. It may choose to restart the kernel or to halt execution entirely. The implementation must
+ //! guarantee that execution never return from this function.
+ //!
+ //! @param message A message describing the reason for termination of execution.
+ //! @param where The source code location at which the panic was triggered. In general, no argument shall be provided
+ //! for this parameter, thus implicitly capturing the location at which the call originates.
[[noreturn]]
auto panic(std::string_view message, std::source_location where = std::source_location::current()) -> void;
} // namespace kstd::os
diff --git a/libs/kstd/kstd/stack.hpp b/libs/kstd/kstd/stack.hpp
index 27e693f2..8c0ae022 100644
--- a/libs/kstd/kstd/stack.hpp
+++ b/libs/kstd/kstd/stack.hpp
@@ -8,183 +8,136 @@
namespace kstd
{
- /**
- * @brief Custom stack implementation mirroring the std::stack to allow for the usage of STL functionality with our
- * custom memory management.
- *
- * @tparam T Element the stack instance should contain.
- * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires
- * access to pop_back(), push_back(), back(), size(), empty() and emplace_back()
- */
+ //! A LIFO-semantics container adaptor.
+ //!
+ //! @tparam T Element the stack instance should contain.
+ //! @tparam Container The adapted container.
template<typename T, typename Container = kstd::vector<T>>
struct stack
{
- using container_type = Container; ///< Type of the underlying container used to implement stack-like interface.
- using value_type = Container::value_type; ///< Type of the elements contained in the underlying container.
- using size_type = Container::size_type; ///< Type of the size in the underlying container.
- using reference = Container::reference; ///< Type of reference to the elements.
- using const_reference = Container::const_reference; ///< Type of constant reference to the elements.
-
- /**
- * @brief Default Constructor.
- */
+ //! Type of the underlying container used to implement stack-like interface.
+ using container_type = Container;
+ //! Type of the elements contained in the underlying container.
+ using value_type = Container::value_type;
+ //! Type of the size in the underlying container.
+ using size_type = Container::size_type;
+ //! Type of reference to the elements.
+ using reference = Container::reference;
+ //! Type of constant reference to the elements.
+ using const_reference = Container::const_reference;
+
+ //! Construct an empty stack.
stack() = default;
stack(stack const &) = delete;
stack(stack &&) = delete;
auto operator=(stack const &) -> stack & = delete;
auto operator=(stack &&) -> stack & = delete;
- /**
- * @brief Constructs data with the given amount of elements containing the given value or alternatively the default
- * constructed value.
- *
- * @param n Amount of elements we want to create and set the given value for.
- * @param initial Inital value of all elements in the underlying data array.
- */
+
+ //! Construct a new stack containing a given number of copies of a given value.
+ //!
+ //! @param n The number of elements.
+ //! @param initial The value of each element.
explicit stack(size_type n, value_type initial = value_type{})
- : _container(n, initial)
+ : m_container(n, initial)
{
// Nothing to do.
}
- /**
- * @brief Constructs data by copying all element from the given exclusive range.
- *
- * @tparam InputIterator Template that should have atleast input iterator characteristics.
- * @param first Input iterator to the first element in the range we want to copy from.
- * @param last Input iterator to one past the last element in the range we want to copy from.
- */
+ //! Construct a stack by filling it with the elements of a given range.
+ //!
+ //! @tparam InputIterator The type of iterators describing this range.
+ //! @param first An iterator to the first element of the range.
+ //! @param last An iterator past the last element of the range.
template<typename InputIterator>
explicit stack(InputIterator first, InputIterator last)
- : _container(first, last)
+ : m_container(first, last)
{
// Nothing to do.
}
- /**
- * @brief Construct data by copying all elements from the initializer list.
- *
- * @param elements List we want to copy all elements from.
- */
+ //! Construct a stack by filling it with the elements of a given initializer list.
+ //!
+ //! @param elements The initializer list whose elements to use as the initial data of the new stack.
explicit stack(std::initializer_list<T> elements)
- : _container(elements)
+ : m_container(elements)
{
// Nothing to do.
}
- /**
- * @brief Copy constructor.
- *
- * @note Allocates underlying data container with the same capacity as stack we are copying from and copies all
- * elements from it.
- *
- * @param other Other instance of stack we want to copy the data from.
- */
+ //! Construct a new stack by copying from an existing one.
+ //!
+ //! @param other The stack to copy from.
stack(stack<T> const & other)
- : _container(other)
+ : m_container(other)
{
// Nothing to do.
}
- /**
- * @brief Destructor.
- */
~stack() = default;
- /**
- * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If
- * that is the case the capacity is increased automatically.
- *
- * @return Current amount of elements.
- */
+ //! Get the number of element currently on this stack.
+ //!
+ //! @return the number of elements currently on this stack.
auto size() const -> size_type
{
- return _container.size();
+ return m_container.size();
}
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
+ //! Get the top element of this stack.
+ //!
+ //! @return a reference to the top element of this stack.
auto top() -> reference
{
- return _container.back();
+ return m_container.back();
}
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
+ //! Get the top element of this stack.
+ //!
+ //! @return a reference to the top element of this stack.
auto top() const -> const_reference
{
- return _container.back();
+ return m_container.back();
}
- /**
- * @brief Appends the given element value to the end of the container. The element is assigned through the
- * assignment operator of the template type. The value is forwarded to the constructor as
- * std::forward<U>(value), meaning it is either moved (rvalue) or copied (lvalue).
- *
- * @note If after the operation the new size() is greater than old capacity() a reallocation takes place,
- * in which case all iterators (including the end() iterator) and all references to the elements are invalidated.
- * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @param value The value of the element to append.
- */
+ //! Push a new element to the top of this stack.
+ //!
+ //! @param value The element to push to the top of this stack.
template<class U>
auto push(U && value) -> void
{
- _container.push_back(std::forward<U>(value));
+ m_container.push_back(std::forward<U>(value));
}
- /**
- * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the
- * template type. The arguments args... are forwarded to the constructor as std::forward<Args>(args)....
- *
- * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case
- * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only
- * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @tparam Args
- * @param args Arguments to forward to the constructor of the element
- * @return value_type&
- */
+ //! Construct a new element on the top of this stack.
+ //!
+ //! @tparam Args The constructor argument types used to construct the new element.
+ //! @param args The arguments for the constructor of the new element.
+ //! @return A reference to the newly constructed element.
+ //!
template<class... Args>
auto emplace(Args &&... args) -> reference
{
- _container.emplace_back(std::forward<Args>(args)...);
+ m_container.emplace_back(std::forward<Args>(args)...);
}
- /**
- * @brief Removes the last element of the container.
- *
- * @note Calling pop_back on an empty container results in halting the
- * further execution. Iterators and references to the last element are invalidated. The end()
- * iterator is also invalidated.
- */
+ //! Pop the top element off this stack.
auto pop() -> void
{
- _container.pop_back();
+ m_container.pop_back();
}
- /**
- * @brief Whether there are currently any items this container or not.
- *
- * @return True if there are no elements, false if there are.
- */
- auto empty() const -> bool
+ //! Check if this stack is empty.
+ //!
+ //! @return @c true iff. there are no elements on the stack, @c false otherwise.
+ [[nodiscard]] auto empty() const -> bool
{
- return _container.empty();
+ return m_container.empty();
}
private:
- container_type _container = {}; ///< Underlying container used by the stack to actually save the data.
+ //! The adapted container.
+ container_type m_container = {};
};
} // namespace kstd
diff --git a/libs/kstd/kstd/string.hpp b/libs/kstd/kstd/string.hpp
index 9978affc..8e42fa2c 100644
--- a/libs/kstd/kstd/string.hpp
+++ b/libs/kstd/kstd/string.hpp
@@ -18,12 +18,11 @@ namespace kstd
{
using string = basic_string<char>;
- /**
- * @brief Converts an integer to a string as if by kstd::format("{}", value).
- * @tparam IntegralType The type of the unsigned integer to convert.
- * @param value The unsigned integer to convert.
- * @return A string representation of the given unsigned integer.
- */
+ //! Convert an integer to a string as if by kstd::format("{}", value).
+ //!
+ //! @tparam IntegralType The type of the unsigned integer to convert.
+ //! @param value The unsigned integer to convert.
+ //! @return A string representation of the given unsigned integer.
template<std::integral IntegralType>
[[nodiscard]] constexpr auto inline to_string(IntegralType value) -> string
{