mijin2/source/mijin/container/inline_array.hpp
2023-05-29 14:51:44 +02:00

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)