134 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #pragma once
 | |
| 
 | |
| #if !defined(MIJIN_CONTAINER_INLINE_ARRAY_HPP_INCLUDED)
 | |
| #define MIJIN_CONTAINER_INLINE_ARRAY_HPP_INCLUDED 1
 | |
| 
 | |
| #include "./boxed_object.hpp"
 | |
| 
 | |
| namespace mijin
 | |
| {
 | |
| 
 | |
| //
 | |
| // public defines
 | |
| //
 | |
| 
 | |
| //
 | |
| // public constants
 | |
| //
 | |
| 
 | |
| //
 | |
| // public types
 | |
| //
 | |
| 
 | |
| template<typename T, std::size_t maxSize>
 | |
| class InlineArray
 | |
| {
 | |
| public:
 | |
|     using element_type = T;
 | |
|     using value_type = std::remove_cv_t<T>;
 | |
|     using size_type = std::size_t;
 | |
|     using difference_type = std::ptrdiff_t;
 | |
|     using pointer = T*;
 | |
|     using const_pointer = const T*;
 | |
|     using reference = T&;
 | |
|     using const_reference = const T&;
 | |
|     using iterator = BoxedObjectIterator<T>;
 | |
|     using const_iterator = BoxedObjectIterator<const T>;
 | |
| private:
 | |
|     BoxedObject<T> elements_[maxSize]; // NOLINT(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
 | |
|     size_type size_ = 0;
 | |
| public:
 | |
|     InlineArray() = default;
 | |
|     InlineArray(const InlineArray& other);
 | |
|     InlineArray(InlineArray&& other) noexcept;
 | |
|     ~InlineArray();
 | |
| 
 | |
|     reference operator[](size_type index);
 | |
|     const_reference operator[](size_type index) const;
 | |
| 
 | |
|     [[nodiscard]] iterator begin() { return BoxedObjectIterator<T>(&elements_[0], &elements_[0], &elements_[size_]); }
 | |
|     [[nodiscard]] const_iterator begin() const { return BoxedObjectIterator<const T>(&elements_[0], &elements_[0], &elements_[size_]); }
 | |
|     [[nodiscard]] const_iterator cbegin() const { return BoxedObjectIterator<const T>(&elements_[0], &elements_[0], &elements_[size_]); }
 | |
|     [[nodiscard]] iterator end() { return BoxedObjectIterator<T>(&elements_[size_], &elements_[0], &elements_[size_]); }
 | |
|     [[nodiscard]] const_iterator end() const { return BoxedObjectIterator<const T>(&elements_[size_], &elements_[0], &elements_[size_]); }
 | |
|     [[nodiscard]] const_iterator cend() const { return BoxedObjectIterator<const T>(&elements_[size_], &elements_[0], &elements_[size_]); }
 | |
| 
 | |
|     [[nodiscard]] constexpr size_type size() const { return size_; }
 | |
|     [[nodiscard]] constexpr size_type capacity() const { return maxSize; }
 | |
|     [[nodiscard]] constexpr bool empty() const { return size_ == 0; }
 | |
|     [[nodiscard]] constexpr reference at(size_type index) {
 | |
|         MIJIN_ASSERT(index < size_, "InlineArray::at() attempt to access out-of-bounds index.");
 | |
|         return elements_[index].get();
 | |
|     }
 | |
|     [[nodiscard]] constexpr const_reference at(size_type index) const {
 | |
|         MIJIN_ASSERT(index < size_, "InlineArray::at() attempt to access out-of-bounds index.");
 | |
|         return elements_[index].get();
 | |
|     }
 | |
| 
 | |
|     void resize(size_type newSize);
 | |
|     void clear() { resize(0); }
 | |
| };
 | |
| 
 | |
| //
 | |
| // public functions
 | |
| //
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| InlineArray<T, numElements>::InlineArray(const InlineArray& other) : size_(other.size_)
 | |
| {
 | |
|     for (size_type idx = 0; idx < size_; ++idx) {
 | |
|         other.elements_[idx].copyTo(elements_[idx]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| InlineArray<T, numElements>::InlineArray(InlineArray&& other) noexcept : size_(other.size_)
 | |
| {
 | |
|     for (size_type idx = 0; idx < size_; ++idx) {
 | |
|         other.elements_[idx].moveTo(elements_[idx]);
 | |
|     }
 | |
|     other.size_ = 0;
 | |
| }
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| InlineArray<T, numElements>::~InlineArray()
 | |
| {
 | |
|     for (std::size_t idx = 0; idx < size_; ++idx) {
 | |
|         elements_[idx].destroy();
 | |
|     }
 | |
| }
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| auto InlineArray<T, numElements>::operator[](size_type index) -> reference
 | |
| {
 | |
|     return at(index);
 | |
| }
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| auto InlineArray<T, numElements>::operator[](size_type index) const -> const_reference
 | |
| {
 | |
|     return at(index);
 | |
| }
 | |
| 
 | |
| template<typename T, std::size_t numElements>
 | |
| void InlineArray<T, numElements>::resize(size_type newSize)
 | |
| {
 | |
|     MIJIN_ASSERT(newSize <= numElements, "InlineArray::resize(): Attempt to resize beyond maximum size.");
 | |
|     if (newSize < size_) {
 | |
|         for (size_type idx = newSize; idx < size_; ++idx) {
 | |
|             elements_[idx].destroy();
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         for (size_type idx = size_; idx < newSize; ++idx) {
 | |
|             elements_[idx].construct();
 | |
|         }
 | |
|     }
 | |
|     size_ = newSize;
 | |
| }
 | |
| 
 | |
| } // namespace mijin
 | |
| 
 | |
| #endif // !defined(MIJIN_CONTAINER_INLINE_ARRAY_HPP_INCLUDED)
 |