summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-05-14 00:02:39 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-05-14 00:41:51 +0200
commit088e03708afe4145a1903f0b20c53cab1899ad50 (patch)
treead31304d28c12ede106fe9fc821d37fe2110bef6
parent5bca42b04941ce132426100b5f99da096b5402b6 (diff)
Add array
-rw-r--r--asl/types/BUILD.bazel22
-rw-r--r--asl/types/array.hpp70
-rw-r--r--asl/types/array_tests.cpp122
3 files changed, 214 insertions, 0 deletions
diff --git a/asl/types/BUILD.bazel b/asl/types/BUILD.bazel
index 16a2a7a..134601b 100644
--- a/asl/types/BUILD.bazel
+++ b/asl/types/BUILD.bazel
@@ -7,6 +7,18 @@ package(
)
cc_library(
+ name = "array",
+ hdrs = [
+ "array.hpp",
+ ],
+ deps = [
+ "//asl/base",
+ "//asl/types:span",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+cc_library(
name = "box",
hdrs = [
"box.hpp",
@@ -125,6 +137,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"],
deps = [
diff --git a/asl/types/array.hpp b/asl/types/array.hpp
new file mode 100644
index 0000000..5fb300a
--- /dev/null
+++ b/asl/types/array.hpp
@@ -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
+
diff --git a/asl/types/array_tests.cpp b/asl/types/array_tests.cpp
new file mode 100644
index 0000000..85b98d1
--- /dev/null
+++ b/asl/types/array_tests.cpp
@@ -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);
+}
+