diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-05-14 00:02:39 +0200 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-05-14 00:41:51 +0200 |
commit | 088e03708afe4145a1903f0b20c53cab1899ad50 (patch) | |
tree | ad31304d28c12ede106fe9fc821d37fe2110bef6 | |
parent | 5bca42b04941ce132426100b5f99da096b5402b6 (diff) |
Add array
-rw-r--r-- | asl/types/BUILD.bazel | 22 | ||||
-rw-r--r-- | asl/types/array.hpp | 70 | ||||
-rw-r--r-- | asl/types/array_tests.cpp | 122 |
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); +} + |