From 4a09d18f1c5960fc1b21a40a25fa3a758c6af5f3 Mon Sep 17 00:00:00 2001 From: Guy Bergel Date: Mon, 31 Aug 2026 12:23:44 -0700 Subject: [PATCH 1/2] add specialization for zero-sized array --- include/camp/array.hpp | 128 +++++++++++++++++++++++++++++++++++++++++ test/array.cpp | 26 +++++++++ 2 files changed, 154 insertions(+) diff --git a/include/camp/array.hpp b/include/camp/array.hpp index e6368e32..9127545f 100644 --- a/include/camp/array.hpp +++ b/include/camp/array.hpp @@ -192,6 +192,134 @@ struct array { value_type elements[N]; }; +template +struct array { + using value_type = T; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = pointer; + using const_iterator = const_pointer; + + constexpr reference at(size_type) + { + throw std::out_of_range{"camp::array::at detected out of range access"}; + } + + constexpr const_reference at(size_type) const + { + throw std::out_of_range{"camp::array::at detected out of range access"}; + } + + CAMP_HOST_DEVICE constexpr reference operator[](size_type) noexcept + { + return *data(); + } + + CAMP_HOST_DEVICE constexpr const_reference operator[]( + size_type) const noexcept + { + return *data(); + } + + reference front() = delete; + const_reference front() const = delete; + reference back() = delete; + const_reference back() const = delete; + + CAMP_HOST_DEVICE constexpr pointer data() noexcept { return nullptr; } + + CAMP_HOST_DEVICE constexpr const_pointer data() const noexcept + { + return nullptr; + } + + CAMP_HOST_DEVICE constexpr iterator begin() noexcept + { + return iterator(data()); + } + + CAMP_HOST_DEVICE constexpr const_iterator begin() const noexcept + { + return const_iterator(data()); + } + + CAMP_HOST_DEVICE constexpr const_iterator cbegin() const noexcept + { + return const_iterator(data()); + } + + CAMP_HOST_DEVICE constexpr iterator end() noexcept + { + return iterator(data()); + } + + CAMP_HOST_DEVICE constexpr const_iterator end() const noexcept + { + return const_iterator(data()); + } + + CAMP_HOST_DEVICE constexpr const_iterator cend() const noexcept + { + return const_iterator(data()); + } + + CAMP_HOST_DEVICE constexpr bool empty() const noexcept { return true; } + + CAMP_HOST_DEVICE constexpr size_type size() const noexcept { return 0; } + + CAMP_HOST_DEVICE constexpr size_type max_size() const noexcept { return 0; } + + CAMP_HOST_DEVICE constexpr void fill(const T&) {} + + CAMP_HOST_DEVICE constexpr void swap(array&) noexcept {} +}; + +template +CAMP_HOST_DEVICE inline constexpr bool operator==(const array&, + const array&) +{ + return true; +} + +template +CAMP_HOST_DEVICE inline constexpr bool operator!=(const array&, + const array&) +{ + return false; +} + +template +CAMP_HOST_DEVICE inline constexpr bool operator<(const array&, + const array&) +{ + return false; +} + +template +CAMP_HOST_DEVICE inline constexpr bool operator<=(const array&, + const array&) +{ + return true; +} + +template +CAMP_HOST_DEVICE inline constexpr bool operator>(const array&, + const array&) +{ + return false; +} + +template +CAMP_HOST_DEVICE inline constexpr bool operator>=(const array&, + const array&) +{ + return true; +} + template CAMP_HOST_DEVICE inline constexpr bool operator==(const array& lhs, const array& rhs) diff --git a/test/array.cpp b/test/array.cpp index 9bf135f9..cfc12afb 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -50,6 +50,23 @@ CAMP_TEST_BEGIN(array, copy_assignment) } CAMP_TEST_END(array, copy_assignment) +CAMP_TEST_BEGIN(array, zero_sized) +{ + camp::array a{}; + camp::array b = {}; + const camp::array& c = a; + + a.fill(3); + camp::swap(a, b); + + return a.empty() && b.empty() && c.empty() && a.size() == 0 + && b.max_size() == 0 && a.data() == nullptr && c.data() == nullptr + && a.begin() == a.end() && c.begin() == c.end() + && a.cbegin() == a.cend() && a == b && !(a != b) && !(a < b) && a <= b + && !(a > b) && a >= b; +} +CAMP_TEST_END(array, zero_sized) + // Not portable as currently implemented TEST(host_array, at) { @@ -77,6 +94,15 @@ TEST(host_array, at) EXPECT_TRUE(exception); } +TEST(host_array, zero_sized_at) +{ + camp::array a{}; + const camp::array& b = a; + + EXPECT_THROW(a.at(0), std::out_of_range); + EXPECT_THROW(b.at(0), std::out_of_range); +} + CAMP_TEST_BEGIN(array, subscript) { camp::array a = {1, 8}; From 9191e946ea4dee59fff291be91ec8a7c2f14acf5 Mon Sep 17 00:00:00 2001 From: Guy Bergel Date: Mon, 31 Aug 2026 12:36:59 -0700 Subject: [PATCH 2/2] split zero-sized test to three tests to make it more understandable --- test/array.cpp | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/test/array.cpp b/test/array.cpp index cfc12afb..4c6a9bd0 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -50,22 +50,47 @@ CAMP_TEST_BEGIN(array, copy_assignment) } CAMP_TEST_END(array, copy_assignment) -CAMP_TEST_BEGIN(array, zero_sized) +CAMP_TEST_BEGIN(array, zero_sized_capacity) +{ + camp::array a{}; + const camp::array& c = a; + + return a.empty() && c.empty() && a.size() == 0 && c.size() == 0 + && a.max_size() == 0 && c.max_size() == 0; +} +CAMP_TEST_END(array, zero_sized_capacity) + +CAMP_TEST_BEGIN(array, zero_sized_data) { camp::array a{}; - camp::array b = {}; const camp::array& c = a; + return a.data() == nullptr && c.data() == nullptr && a.begin() == a.end() + && c.begin() == c.end() && a.cbegin() == a.cend() + && c.cbegin() == c.cend(); +} +CAMP_TEST_END(array, zero_sized_data) + +CAMP_TEST_BEGIN(array, zero_sized_modifiers) +{ + camp::array a{}; + camp::array b = {}; + a.fill(3); camp::swap(a, b); - return a.empty() && b.empty() && c.empty() && a.size() == 0 - && b.max_size() == 0 && a.data() == nullptr && c.data() == nullptr - && a.begin() == a.end() && c.begin() == c.end() - && a.cbegin() == a.cend() && a == b && !(a != b) && !(a < b) && a <= b - && !(a > b) && a >= b; + return a.empty() && b.empty() && a.size() == 0 && b.size() == 0; +} +CAMP_TEST_END(array, zero_sized_modifiers) + +CAMP_TEST_BEGIN(array, zero_sized_comparisons) +{ + camp::array a{}; + camp::array b = {}; + + return a == b && !(a != b) && !(a < b) && a <= b && !(a > b) && a >= b; } -CAMP_TEST_END(array, zero_sized) +CAMP_TEST_END(array, zero_sized_comparisons) // Not portable as currently implemented TEST(host_array, at)