From 2cb9f4f2515cc3f6ddaf1806630114118dddf4b5 Mon Sep 17 00:00:00 2001 From: Patrick Roberts Date: Sat, 8 Feb 2025 14:06:16 -0600 Subject: [PATCH] Add some constexpr tests --- .../beman/any_view/detail/any_iterator.hpp | 3 +- include/beman/any_view/detail/concepts.hpp | 2 +- .../any_view/detail/intrusive_small_ptr.hpp | 2 +- .../any_view/detail/iterator_adaptor.hpp | 6 ++- .../beman/any_view/detail/view_adaptor.hpp | 7 +++ tests/beman/any_view/CMakeLists.txt | 1 + tests/beman/any_view/constexpr.test.cpp | 54 +++++++++++++++++++ 7 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 tests/beman/any_view/constexpr.test.cpp diff --git a/include/beman/any_view/detail/any_iterator.hpp b/include/beman/any_view/detail/any_iterator.hpp index fda8b87..81b0041 100644 --- a/include/beman/any_view/detail/any_iterator.hpp +++ b/include/beman/any_view/detail/any_iterator.hpp @@ -152,7 +152,8 @@ class any_iterator { constexpr auto operator-=(difference_type offset) -> any_iterator& requires random_access { - *iterator_ptr -= offset; + // TODO: should virtual function for operator-= be provided to avoid signed overflow for max difference type? + *this += -offset; return *this; } diff --git a/include/beman/any_view/detail/concepts.hpp b/include/beman/any_view/detail/concepts.hpp index 0e071f7..f25cbe8 100644 --- a/include/beman/any_view/detail/concepts.hpp +++ b/include/beman/any_view/detail/concepts.hpp @@ -34,7 +34,7 @@ concept contiguous_iterator_compatible_with = random_access_iterator_compatible_with and (not std::derived_from or std::contiguous_iterator); -template +template concept contiguous_reference_convertible_to = std::convertible_to and (not std::derived_from or diff --git a/include/beman/any_view/detail/intrusive_small_ptr.hpp b/include/beman/any_view/detail/intrusive_small_ptr.hpp index 9ba0f56..896da9c 100644 --- a/include/beman/any_view/detail/intrusive_small_ptr.hpp +++ b/include/beman/any_view/detail/intrusive_small_ptr.hpp @@ -77,7 +77,7 @@ class intrusive_small_ptr { if (index == index_type::is_inplace) { other.get_inplace()->copy_to(&inplace); } else { - pointer = other.pointer->copy(); + pointer = other ? other.pointer->copy() : nullptr; } } diff --git a/include/beman/any_view/detail/iterator_adaptor.hpp b/include/beman/any_view/detail/iterator_adaptor.hpp index 3893a2c..8e93520 100644 --- a/include/beman/any_view/detail/iterator_adaptor.hpp +++ b/include/beman/any_view/detail/iterator_adaptor.hpp @@ -3,6 +3,7 @@ #ifndef BEMAN_ANY_VIEW_DETAIL_ITERATOR_ADAPTOR_HPP #define BEMAN_ANY_VIEW_DETAIL_ITERATOR_ADAPTOR_HPP +#include #include #include @@ -71,7 +72,7 @@ class iterator_adaptor : public iterator_interface RValueRefT override { return std::ranges::iter_move(iterator); } [[nodiscard]] constexpr auto operator->() const -> pointer override { - if constexpr (contiguous) { + if constexpr (contiguous and contiguous_reference_convertible_to, RefT>) { return std::to_address(iterator); } else { unreachable(); @@ -129,6 +130,9 @@ class iterator_adaptor : public iterator_interface bool override { return iterator == sentinel; } + + // ICE workaround for GCC + constexpr ~iterator_adaptor() noexcept override {} }; } // namespace beman::any_view::detail diff --git a/include/beman/any_view/detail/view_adaptor.hpp b/include/beman/any_view/detail/view_adaptor.hpp index efbcc31..b3f81a1 100644 --- a/include/beman/any_view/detail/view_adaptor.hpp +++ b/include/beman/any_view/detail/view_adaptor.hpp @@ -23,6 +23,10 @@ class view_adaptor : public view_interface void override { if constexpr (std::copy_constructible) { ::new (destination) view_adaptor(*this); @@ -62,6 +66,9 @@ class view_adaptor : public view_interface + +#include + +#include + +using beman::any_view::any_view; + +#if BEMAN_ANY_VIEW_USE_ENUM() +using enum beman::any_view::any_view_options; + +template +using proxy_any_view = any_view; +#elif BEMAN_ANY_VIEW_USE_TRAITS() +template +struct proxy_traits { + using reference_type = ValueT; +}; + +template +using proxy_any_view = any_view>; +#elif BEMAN_ANY_VIEW_USE_NAMED() +using beman::any_view::type; + +template +using proxy_any_view = any_view}>; +#endif + +constexpr auto sum(proxy_any_view> views) { + auto result = 0; + + for (auto view : views) { + for (const auto value : view) { + result += value; + } + } + + return result; +} + +TEST(ConstexprTest, sum_vector_of_vector) { + static_assert(15 == sum(std::vector{std::vector{1, 2}, std::vector{3, 4}, std::vector{5}})); + EXPECT_EQ(15, sum(std::vector{std::vector{1, 2}, std::vector{3, 4}, std::vector{5}})); +} + +TEST(ConstexprTest, sum_transform_view_of_iota) { + constexpr auto iota = [](int n) { return std::views::iota(1) | std::views::take(n); }; + constexpr auto view = iota(5) | std::views::transform(iota); + + static_assert(35 == sum(view)); + EXPECT_EQ(35, sum(view)); +}