based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit fa7619b77db3f4393d1b318cad5bf185c71c45e3
parent cb5cb36c3a6920d7e3ec8243eac75b181d642ef7
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Tue, 24 Jun 2025 20:24:50 +0200

Array implementation

Diffstat:
M include/based/character/mapper.hpp | + -
M include/based/container/array.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -----------------
M include/based/integral/types.hpp | +

3 files changed, 221 insertions(+), 55 deletions(-)


diff --git a/ include/based/character/mapper.hpp b/ include/based/character/mapper.hpp

@@ -60,7 +60,7 @@ class Mapper


public:
static constexpr bool predicate(Character chr) { return m_predicate(chr); }
static constexpr Character map(MappedType value) { return reverse[value]; }
static constexpr Character map(MappedType value) { return reverse[value]; }
static constexpr MappedType map(Character chr) { return direct[chr.ord()]; }
};

diff --git a/ include/based/container/array.hpp b/ include/based/container/array.hpp

@@ -1,70 +1,235 @@

#pragma once

#include <array>
#include <algorithm>

#include "based/concept/is_integral.hpp"
#include "based/integral/literals.hpp"
#include "based/integral/types.hpp"
#include "based/memory/addressof.hpp"

#define TEMPLATE template<class T, trait::IsUnsignedIntegral U, U N>
#define ARRAY Array<T, U, N>

namespace based
{

template<class T, class U, U n>
class Array : public std::array<T, U64::cast(n).value>
TEMPLATE
class Array
{
using Base = std::array<T, U64::cast(n).value>;

static constexpr auto cast(U pos)
{
return static_cast<Base::size_type>(pos.value);
}

static constexpr auto cast(Base::size_type pos)
{
return static_cast<U>(pos.value);
}
T m_instance[N != U(0_u) ? N.value : U(1_u).value]; // NOLINT(*array*)

public:
using const_iterator = Base::const_iterator;
using const_pointer = Base::const_pointer;
using const_reference = Base::const_reference;
using const_reverse_iterator = Base::const_reverse_iterator;
using iterator = Base::iterator;
using pointer = Base::pointer;
using reference = Base::reference;
using reverse_iterator = Base::reverse_iterator;
using value_type = Base::value_type;

using difference_type = U;
using value_type = T;
using size_type = U;
using difference_type = PtrDiffT;

using iterator = value_type*;
using const_iterator = const value_type*;

using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;

using pointer = T*;
using const_pointer = const T*;

using reference = value_type&;
using const_reference = const value_type&;

// Element access
[[nodiscard]] constexpr reference operator[](size_type idx);
[[nodiscard]] constexpr reference front();
[[nodiscard]] constexpr reference back();
[[nodiscard]] constexpr pointer data();

[[nodiscard]] constexpr const_reference operator[](size_type idx) const;
[[nodiscard]] constexpr const_reference front() const;
[[nodiscard]] constexpr const_reference back() const;
[[nodiscard]] constexpr const_pointer data() const;

// Iterators.
[[nodiscard]] constexpr iterator begin();
[[nodiscard]] constexpr iterator end();

[[nodiscard]] constexpr const_iterator begin() const;
[[nodiscard]] constexpr const_iterator end() const;

[[nodiscard]] constexpr const_iterator cbegin() const;
[[nodiscard]] constexpr const_iterator cend() const;

[[nodiscard]] constexpr reverse_iterator rbegin();
[[nodiscard]] constexpr reverse_iterator rend();

[[nodiscard]] constexpr const_reverse_iterator rbegin() const;
[[nodiscard]] constexpr const_reverse_iterator rend() const;

[[nodiscard]] constexpr const_reverse_iterator crbegin() const;
[[nodiscard]] constexpr const_reverse_iterator crend() const;

// Capacity
[[nodiscard]] constexpr size_type size() const { return N; }
[[nodiscard]] constexpr size_type max_size() const { return N; }

[[nodiscard]] constexpr bool empty() const { return size() == 0; }

[[nodiscard]] constexpr const_reference at(size_type pos) const
{
return Base::at(cast(pos));
}

[[nodiscard]] constexpr reference at(size_type pos)
{
return Base::at(cast(pos));
}

[[nodiscard]] constexpr const_reference operator[](size_type pos) const
{
return Base::operator[](cast(pos));
}

[[nodiscard]] constexpr reference operator[](size_type pos)
{
return Base::operator[](cast(pos));
}

[[nodiscard]] constexpr size_type size() const noexcept
{
return cast(Base::size());
}

[[nodiscard]] constexpr size_type max_size() const noexcept
{
return cast(Base::max_size());
}
// Operations
constexpr void fill(const value_type& value);
constexpr void swap(Array& that) noexcept;
};

TEMPLATE
auto constexpr operator==(const ARRAY& lhs, const ARRAY& rhs) -> bool
{
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

TEMPLATE
auto constexpr operator<=>(const ARRAY& lhs, const ARRAY& rhs)
{
return std::lexicographical_compare_three_way(
lhs.begin(), lhs.end(), rhs.begin(), rhs.end()
);
}

TEMPLATE
inline auto constexpr ARRAY::fill(const ARRAY::value_type& value) -> void
{
std::fill_n(begin(), size(), value);
}

TEMPLATE
inline auto constexpr ARRAY::swap(ARRAY& that) noexcept -> void
{
std::swap_ranges(begin(), end(), that.begin());
}

TEMPLATE
auto constexpr swap(ARRAY& lhs, ARRAY& rhs) noexcept -> void
{
lhs.swap(rhs);
}

TEMPLATE
inline auto constexpr ARRAY::begin() -> ARRAY::iterator
{
return iterator(addressof(m_instance[0]));
}

TEMPLATE
inline auto constexpr ARRAY::begin() const -> ARRAY::const_iterator
{
return const_iterator(addressof(m_instance[0]));
}

TEMPLATE
inline auto constexpr ARRAY::end() -> ARRAY::iterator
{
return iterator(addressof(m_instance[N]));
}

TEMPLATE
inline auto constexpr ARRAY::end() const -> ARRAY::const_iterator
{
return const_iterator(addressof(m_instance[N]));
}

TEMPLATE
inline auto constexpr ARRAY::rbegin() -> ARRAY::reverse_iterator
{
return reverse_iterator(end());
}

TEMPLATE
inline auto constexpr ARRAY::rbegin() const -> ARRAY::const_reverse_iterator
{
return const_reverse_iterator(end());
}

TEMPLATE
inline auto constexpr ARRAY::rend() -> ARRAY::reverse_iterator
{
return reverse_iterator(begin());
}

TEMPLATE
inline auto constexpr ARRAY::rend() const -> ARRAY::const_reverse_iterator
{
return const_reverse_iterator(begin());
}

TEMPLATE
inline auto constexpr ARRAY::cbegin() const -> ARRAY::const_iterator
{
return const_iterator(addressof(m_instance[0]));
}

TEMPLATE
inline auto constexpr ARRAY::cend() const -> ARRAY::const_iterator
{
return const_iterator(addressof(m_instance[N]));
}

TEMPLATE
inline auto constexpr ARRAY::crbegin() const -> ARRAY::const_reverse_iterator
{
return const_reverse_iterator(end());
}

TEMPLATE
inline auto constexpr ARRAY::crend() const -> ARRAY::const_reverse_iterator
{
return const_reverse_iterator(begin());
}

TEMPLATE
inline auto constexpr ARRAY::operator[](size_type idx) -> ARRAY::reference
{
return m_instance[idx.value];
}

TEMPLATE
inline auto constexpr ARRAY::operator[](size_type idx) const
-> ARRAY::const_reference
{
return m_instance[idx.value];
}

TEMPLATE
inline auto constexpr ARRAY::front() -> ARRAY::reference
{
return *begin();
}

TEMPLATE
inline auto constexpr ARRAY::front() const -> ARRAY::const_reference
{
return *begin();
}

TEMPLATE
inline auto constexpr ARRAY::back() -> ARRAY::reference
{
return N ? *(end() - 1) : *end();
}

TEMPLATE
inline auto constexpr ARRAY::back() const -> ARRAY::const_reference
{
return N ? *(end() - 1) : *end();
}

TEMPLATE
inline auto constexpr ARRAY::data() -> ARRAY::pointer
{
return addressof(m_instance[0]);
}

TEMPLATE
inline auto constexpr ARRAY::data() const -> ARRAY::const_pointer
{
return addressof(m_instance[0]);
}

#undef TEMPLATE
#undef ARRAY

} // namespace based

diff --git a/ include/based/integral/types.hpp b/ include/based/integral/types.hpp

@@ -10,6 +10,7 @@ namespace based

// NOLINTBEGIN(google-runtime-int)

using SizeT = unsigned long long int;
using PtrDiffT = signed long long int;

#define BASED_DETAIL_OP_UNARY(Prefix, Name, Index) \
auto Name(Prefix##8)->Prefix##8; \