From 088e03708afe4145a1903f0b20c53cab1899ad50 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 14 May 2025 00:02:39 +0200 Subject: Add array --- asl/types/BUILD.bazel | 22 +++++++++ asl/types/array.hpp | 70 ++++++++++++++++++++++++++ asl/types/array_tests.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 asl/types/array.hpp create mode 100644 asl/types/array_tests.cpp 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 @@ -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"], 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 +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>*; + return static_cast(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 + requires (kSpanSize == kSize || kSpanSize == dynamic_size) + constexpr operator span() const // NOLINT(*explicit*) + { + return as_span(); + } + + template + requires (kSpanSize == kSize || kSpanSize == dynamic_size) + constexpr operator span() // NOLINT(*explicit*) + { + return as_span(); + } + + constexpr auto as_span(this auto&& self) + { + using type = un_ref_t>; + return span{self.data(), self.size()}; + } + + constexpr auto&& operator[](this auto&& self, isize_t i) + { + ASL_ASSERT(i >= 0 && i <= self.size()); + return std::forward_like(std::forward(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) == 32); + +static_assert(asl::default_constructible>); +static_assert(asl::trivially_default_constructible>); + +static_assert(asl::default_constructible>); +static_assert(asl::trivially_default_constructible>); +static_assert(asl::trivially_copy_constructible>); +static_assert(asl::trivially_copy_assignable>); +static_assert(asl::trivially_move_constructible>); +static_assert(asl::trivially_move_assignable>); + +static_assert(asl::default_constructible>); +static_assert(!asl::trivially_default_constructible>); + +static_assert(asl::trivially_destructible>); +static_assert(asl::trivially_destructible>); +static_assert(!asl::trivially_destructible>); + +static_assert(asl::copyable>); +static_assert(!asl::copyable>); +static_assert(!asl::copyable>); + +static_assert(asl::moveable>); +static_assert(asl::moveable>); +static_assert(!asl::moveable>); + +ASL_TEST(construct_default) +{ + asl::array arr{}; + + ASL_TEST_EXPECT(static_cast(&arr) == static_cast(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 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::span>); +static_assert(asl::convertible_to, asl::span>); + +ASL_TEST(sized_span) +{ + asl::array arr{10, 11, 12, 13}; + const asl::span 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 arr{10, 11, 12, 13}; + const asl::span 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 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); +} + -- cgit