#ifndef ARBUTILS_UNIQUEPTRLIST_HPP #define ARBUTILS_UNIQUEPTRLIST_HPP #include "BorrowedPtr.hpp" namespace ArbUt { /// @brief Collection of pointers that is owned by the list. When the list exits scope, the destructor on all /// pointers will be called. template class UniquePtrList { private: std::vector _vector; using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; public: inline UniquePtrList() noexcept : _vector() {} /// @brief Initialises a UniquePtrList from a std::vector of raw pointers. /// @param vec A std::vector of raw pointers. inline UniquePtrList(const std::vector& vec) noexcept : _vector(vec) {} /// @brief Initialises a UniquePtrList with a certain capacity reserved for use. This does not set immediate /// size. /// @param capacity The desired capacity. explicit inline UniquePtrList(size_t capacity) : _vector() { _vector.reserve(capacity); } /// @brief Initialises a UniquePtrList from a initialiser_list. /// @param l A initialiser_list inline UniquePtrList(const std::initializer_list& l) noexcept : _vector(l) {} /// @brief Initialises a UniquePtrList from a raw pointer range. /// @param begin The raw pointer to the start of the list. /// @param end The raw pointer to the end of the list. inline UniquePtrList(ValueT* const* begin, ValueT* const* end) noexcept : _vector(begin, end) {} UniquePtrList(const UniquePtrList&) = delete; UniquePtrList& operator=(const UniquePtrList&) = delete; ~UniquePtrList() noexcept { Clear(); } /// @brief Clears the UniquePtrList, and run the destructor on all containing pointers. inline void Clear() noexcept { for (auto& i : _vector) { delete i; } } /// @brief Borrow a pointer at a certain index. /// @param index The index to retrieve. /// @return A borrowed pointer reference to the containing raw pointer. inline BorrowedPtr At(size_t index) const { #ifndef NO_ASSERT if (index >= _vector.size()) { std::stringstream ss; ss << "Index " << index << " is out of bounds."; throw ArbUt::Exception(ss.str()); } #endif return _vector[index]; } /// @brief Returns a raw pointer at an index, and releases ownership. Proper handling of the memory is assumed /// to be done by the taker. /// @param index The index to get the pointer from. /// @return A raw pointer. ValueT* TakeOwnership(size_t index) { auto p = _vector[index]; _vector[index] = nullptr; return p; } /// @brief Swaps two pointers at indices with each other. /// @param indexA The first index to swap from. /// @param indexB The second index to swap from void Swap(size_t indexA, size_t indexB) { auto temp = _vector[indexA]; _vector[indexA] = _vector[indexB]; _vector[indexB] = temp; } /// @brief Sets a pointer to a certain index. If an item already existed at that index, it's destructor will be /// called. /// @param index The index to set the pointer to. /// @param ptr The pointer to store. void Set(size_t index, ValueT* ptr) { delete _vector[index]; _vector[index] = ptr; } /// @brief Removes a pointer at a certain index. It's destructor will be called. /// @param index The index to remove. inline void Remove(size_t index) { #ifndef NO_ASSERT if (index >= _vector.size()) { std::stringstream ss; ss << "Index " << index << " is out of bounds."; throw ArbUt::Exception(ss.str()); } #endif delete _vector[index]; _vector.erase(_vector.begin() + index); } /// @brief Check whether a pointer is contained in the list. /// @param value The value to check for. /// @return True if the list contains the pointer, false otherwise. inline bool Contains(const BorrowedPtr& value) const noexcept { return std::find(_vector.begin(), _vector.end(), value) != _vector.end(); } /// @brief Find the index of the first occurrence of a value in the list, return -1 if none is found. /// @param value The value we want the index for. /// @return The index of the first occurrence of the value in the list, or -1 if none is found. inline size_t IndexOf(const BorrowedPtr& value) const noexcept { const auto& it = std::find(_vector.begin(), _vector.end(), value); if (it == _vector.end()) return -1; return std::distance(_vector.begin(), it); } /// @brief Append a pointer to the list. /// @param value The pointer to push to the list. inline void Append(ValueT* value) { _vector.push_back(value); } /// @brief Borrow a pointer at a certain index. /// @param index The index to retrieve. /// @return A borrowed pointer reference to the containing raw pointer. inline BorrowedPtr operator[](size_t index) const { return At(index); } /// @brief Returns the number of pointers contained. /// @return The number of pointers contained. [[nodiscard]] inline size_t Count() const noexcept { return _vector.size(); } /// @brief returns an iterator to the beginning of the specified bucket iterator begin() noexcept { return _vector.begin(); } /// @brief returns an iterator to the beginning of the specified bucket iterator end() noexcept { return _vector.end(); } /// @brief returns an iterator to the end of the specified bucket const_iterator begin() const noexcept { return _vector.begin(); } /// @brief returns an iterator to the end of the specified bucket const_iterator end() const noexcept { return _vector.end(); } /// @brief Return a raw pointer to the beginning of the list. /// @return A raw array pointer to the beginning of the list. ValueT* const* RawData() const noexcept { return _vector.data(); } /// @brief Returns a std::vector representation of the current list. /// @return A std::vector representation of the current list. const std::vector& GetStdList() const noexcept { return _vector; } /// @brief Returns a std::vector representation of the current list. /// @return A std::vector representation of the current list. std::vector& GetStdList() noexcept { return _vector; } }; } #endif // ARBUTILS_UNIQUEPTRLIST_HPP