212 lines
5.4 KiB
C++
212 lines
5.4 KiB
C++
/*
|
|
* Copyright 2015 - 2025 gary@drinkingtea.net
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "bit.hpp"
|
|
#include "def.hpp"
|
|
#include "error.hpp"
|
|
#include "initializerlist.hpp"
|
|
#include "iterator.hpp"
|
|
#include "math.hpp"
|
|
#include "new.hpp"
|
|
#include "types.hpp"
|
|
#include "utility.hpp"
|
|
|
|
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
|
|
|
namespace ox {
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
class Array {
|
|
|
|
public:
|
|
using value_type = T;
|
|
using size_type = std::size_t;
|
|
|
|
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
|
|
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
|
|
|
|
private:
|
|
T m_items[ArraySize]{};
|
|
|
|
public:
|
|
constexpr Array() noexcept = default;
|
|
|
|
template<typename ...Args>
|
|
constexpr Array(Args ...list) noexcept: m_items{std::move(list)...} {
|
|
}
|
|
|
|
constexpr Array(std::initializer_list<T> list) noexcept;
|
|
|
|
constexpr Array(const Array &other);
|
|
|
|
constexpr Array(Array &&other) noexcept;
|
|
|
|
constexpr ~Array() = default;
|
|
|
|
constexpr iterator<> begin() noexcept {
|
|
return iterator<>(&m_items[0], 0, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<> end() noexcept {
|
|
return iterator<>(&m_items[0], ArraySize, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<const T&, const T*> begin() const noexcept {
|
|
return iterator<const T&, const T*>(&m_items[0], 0, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<const T&, const T*> end() const noexcept {
|
|
return iterator<const T&, const T*>(&m_items[0], ArraySize, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<T&, T*, true> rbegin() noexcept {
|
|
return iterator<T&, T*, true>(&m_items[0], ArraySize - 1, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<T&, T*, true> rend() noexcept {
|
|
return iterator<T&, T*, true>(&m_items[0], MaxValue<size_type>, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
|
|
return iterator<const T&, const T*, true>(m_items, ArraySize - 1, ArraySize);
|
|
}
|
|
|
|
constexpr iterator<const T&, const T*, true> rend() const noexcept {
|
|
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, ArraySize);
|
|
}
|
|
|
|
constexpr bool operator==(const Array &other) const;
|
|
|
|
constexpr Array &operator=(const Array &other);
|
|
|
|
constexpr Array &operator=(Array &&other) noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr T &operator[](std::size_t i) noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr const T &operator[](std::size_t i) const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr std::size_t size() const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr T *data() noexcept {
|
|
return m_items;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr const T *data() const noexcept {
|
|
return m_items;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr bool contains(const T&) const;
|
|
|
|
};
|
|
|
|
template<typename T, std::size_t ArraySize, typename RefType, bool reverse>
|
|
using ArrayIt = typename Array<T, ArraySize>::template iterator<RefType, reverse>;
|
|
|
|
template<typename T, std::size_t ArraySize, typename RefType, bool reverse>
|
|
constexpr ArrayIt<T, ArraySize, RefType, reverse> operator+(std::size_t n, const ArrayIt<T, ArraySize, RefType, reverse> &a) {
|
|
return a + n;
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr Array<T, ArraySize>::Array(std::initializer_list<T> list) noexcept {
|
|
for (auto i = 0ul; auto &item : list) {
|
|
this->operator[](i) = item;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr Array<T, ArraySize>::Array(const Array &other) {
|
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
|
m_items[i] = T(other.m_items[i]);
|
|
}
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr Array<T, ArraySize>::Array(Array &&other) noexcept {
|
|
if (this != &other) {
|
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
|
m_items[i] = T(std::move(other.m_items[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr bool Array<T, ArraySize>::operator==(const Array &other) const {
|
|
if (std::is_constant_evaluated()) {
|
|
for (std::size_t i = 0; i < ArraySize; i++) {
|
|
if (!(m_items[i] == other.m_items[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
} else {
|
|
return memcmp(this, &other, sizeof(*this)) == 0;
|
|
}
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(const Array &other) {
|
|
if (this != &other) {
|
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
|
m_items[i] = other.m_items[i];
|
|
}
|
|
}
|
|
return *this;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noexcept {
|
|
if (this != &other) {
|
|
for (std::size_t i = 0; i < ArraySize; ++i) {
|
|
m_items[i] = std::move(other.m_items[i]);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
|
|
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
|
|
return m_items[i];
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
|
|
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
|
|
return m_items[i];
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr std::size_t Array<T, ArraySize>::size() const noexcept {
|
|
return ArraySize;
|
|
}
|
|
|
|
template<typename T, std::size_t ArraySize>
|
|
constexpr bool Array<T, ArraySize>::contains(const T &v) const {
|
|
for (std::size_t i = 0; i < ArraySize; i++) {
|
|
if (m_items[i] == v) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
OX_CLANG_NOWARN_END
|