Add array

This commit is contained in:
2025-05-14 00:02:39 +02:00
parent 5bca42b049
commit 088e03708a
3 changed files with 214 additions and 0 deletions

View File

@ -6,6 +6,18 @@ package(
default_applicable_licenses = ["//:license"],
)
cc_library(
name = "array",
hdrs = [
"array.hpp",
],
deps = [
"//asl/base",
"//asl/types:span",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "box",
hdrs = [
@ -124,6 +136,16 @@ cc_test(
],
)
cc_test(
name = "array_tests",
srcs = ["array_tests.cpp"],
deps = [
"//asl/tests:utils",
"//asl/testing",
"//asl/types:array",
],
)
cc_test(
name = "box_tests",
srcs = ["box_tests.cpp"],

70
asl/types/array.hpp Normal file
View File

@ -0,0 +1,70 @@
// Copyright 2025 Steven Le Rouzic
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include "asl/base/assert.hpp"
#include "asl/base/meta.hpp"
#include "asl/base/utility.hpp"
#include "asl/types/span.hpp"
namespace asl
{
template<is_object T, int64_t kSize>
requires (kSize > 0)
struct array
{
T m_data[kSize];
[[nodiscard]] constexpr bool is_empty() const { return false; }
[[nodiscard]] constexpr int64_t size() const { return kSize; }
constexpr auto data(this auto&& self)
{
using return_type = un_ref_t<copy_cref_t<decltype(self), T>>*;
return static_cast<return_type>(self.m_data);
}
constexpr auto begin(this auto&& self)
{
return contiguous_iterator{self.data()};
}
constexpr auto end(this auto&& self)
{
return contiguous_iterator{self.data() + kSize};
}
template<int64_t kSpanSize>
requires (kSpanSize == kSize || kSpanSize == dynamic_size)
constexpr operator span<const T, kSpanSize>() const // NOLINT(*explicit*)
{
return as_span();
}
template<int64_t kSpanSize>
requires (kSpanSize == kSize || kSpanSize == dynamic_size)
constexpr operator span<T, kSpanSize>() // NOLINT(*explicit*)
{
return as_span();
}
constexpr auto as_span(this auto&& self)
{
using type = un_ref_t<copy_cref_t<decltype(self), T>>;
return span<type, kSize>{self.data(), self.size()};
}
constexpr auto&& operator[](this auto&& self, isize_t i)
{
ASL_ASSERT(i >= 0 && i <= self.size());
return std::forward_like<decltype(self)>(std::forward<decltype(self)>(self).data()[i]);
}
};
} // namespace asl

122
asl/types/array_tests.cpp Normal file
View File

@ -0,0 +1,122 @@
// Copyright 2025 Steven Le Rouzic
//
// SPDX-License-Identifier: BSD-3-Clause
#include "asl/types/array.hpp"
#include "asl/testing/testing.hpp"
#include "asl/tests/types.hpp"
static_assert(sizeof(asl::array<int32_t, 8>) == 32);
static_assert(asl::default_constructible<asl::array<int, 6>>);
static_assert(asl::trivially_default_constructible<asl::array<int, 6>>);
static_assert(asl::default_constructible<asl::array<TrivialType, 6>>);
static_assert(asl::trivially_default_constructible<asl::array<TrivialType, 6>>);
static_assert(asl::trivially_copy_constructible<asl::array<TrivialType, 6>>);
static_assert(asl::trivially_copy_assignable<asl::array<TrivialType, 6>>);
static_assert(asl::trivially_move_constructible<asl::array<TrivialType, 6>>);
static_assert(asl::trivially_move_assignable<asl::array<TrivialType, 6>>);
static_assert(asl::default_constructible<asl::array<TrivialTypeDefaultValue, 6>>);
static_assert(!asl::trivially_default_constructible<asl::array<TrivialTypeDefaultValue, 6>>);
static_assert(asl::trivially_destructible<asl::array<int, 6>>);
static_assert(asl::trivially_destructible<asl::array<TrivialType, 6>>);
static_assert(!asl::trivially_destructible<asl::array<WithDestructor, 6>>);
static_assert(asl::copyable<asl::array<Copyable, 6>>);
static_assert(!asl::copyable<asl::array<MoveableOnly, 6>>);
static_assert(!asl::copyable<asl::array<Pinned, 6>>);
static_assert(asl::moveable<asl::array<Copyable, 6>>);
static_assert(asl::moveable<asl::array<MoveableOnly, 6>>);
static_assert(!asl::moveable<asl::array<Pinned, 6>>);
ASL_TEST(construct_default)
{
asl::array<int, 4> arr{};
ASL_TEST_EXPECT(static_cast<void*>(&arr) == static_cast<void*>(arr.data()));
ASL_TEST_EXPECT(arr[0] == 0);
ASL_TEST_EXPECT(arr[1] == 0);
ASL_TEST_EXPECT(arr[2] == 0);
ASL_TEST_EXPECT(arr[3] == 0);
ASL_TEST_EXPECT(arr.data()[0] == 0); // NOLINT
ASL_TEST_EXPECT(arr.data()[1] == 0); // NOLINT
ASL_TEST_EXPECT(arr.data()[2] == 0); // NOLINT
ASL_TEST_EXPECT(arr.data()[3] == 0); // NOLINT
}
ASL_TEST(construct)
{
asl::array<int, 4> arr{10, 11, 12, 13};
ASL_TEST_EXPECT(arr[0] == 10);
ASL_TEST_EXPECT(arr[1] == 11);
ASL_TEST_EXPECT(arr[2] == 12);
ASL_TEST_EXPECT(arr[3] == 13);
ASL_TEST_EXPECT(arr.data()[0] == 10); // NOLINT
ASL_TEST_EXPECT(arr.data()[1] == 11); // NOLINT
ASL_TEST_EXPECT(arr.data()[2] == 12); // NOLINT
ASL_TEST_EXPECT(arr.data()[3] == 13); // NOLINT
}
static_assert(asl::convertible_to<asl::array<int, 4>, asl::span<int, 4>>);
static_assert(asl::convertible_to<asl::array<int, 4>, asl::span<int>>);
ASL_TEST(sized_span)
{
asl::array<int, 4> arr{10, 11, 12, 13};
const asl::span<int, 4> s1 = arr;
ASL_TEST_EXPECT(s1.size() == 4);
ASL_TEST_EXPECT(s1.data() == arr.data());
ASL_TEST_EXPECT(s1[0] == 10);
ASL_TEST_EXPECT(s1[1] == 11);
ASL_TEST_EXPECT(s1[2] == 12);
ASL_TEST_EXPECT(s1[3] == 13);
}
ASL_TEST(unsized_span)
{
asl::array<int, 4> arr{10, 11, 12, 13};
const asl::span<int> s2 = arr;
ASL_TEST_EXPECT(s2.size() == 4);
ASL_TEST_EXPECT(s2[0] == 10);
ASL_TEST_EXPECT(s2[1] == 11);
ASL_TEST_EXPECT(s2[2] == 12);
ASL_TEST_EXPECT(s2[3] == 13);
}
ASL_TEST(iterator)
{
const asl::array<int, 4> arr{10, 11, 12, 13};
auto it = arr.begin();
auto end = arr.end();
ASL_TEST_ASSERT(it != end);
ASL_TEST_EXPECT(*it == 10);
it++;
ASL_TEST_ASSERT(it != end);
ASL_TEST_EXPECT(*it == 11);
it++;
ASL_TEST_ASSERT(it != end);
ASL_TEST_EXPECT(*it == 12);
it++;
ASL_TEST_ASSERT(it != end);
ASL_TEST_EXPECT(*it == 13);
it++;
ASL_TEST_ASSERT(it == end);
}