diff --git a/include/flux/op/cartesian_base.hpp b/include/flux/op/cartesian_base.hpp index b25d799b..6d2dbabb 100644 --- a/include/flux/op/cartesian_base.hpp +++ b/include/flux/op/cartesian_base.hpp @@ -270,9 +270,20 @@ struct cartesian_traits_base_impl { static constexpr auto last(Self& self) -> cursor_t requires cartesian_is_bounded { - auto cur = first(self); - std::get<0>(cur) = flux::last(get_base<0>(self)); - return cur; + if constexpr (CartesianKind == cartesian_kind::product) { + auto cur = first(self); + bool any_is_empty = std::apply([](auto& /*ignored*/, auto&... bases) { + return (flux::is_empty(bases) || ...); + }, self.bases_); + if (!any_is_empty) { + std::get<0>(cur) = flux::last(get_base<0>(self)); + } + return cur; + } else { + auto cur = first(self); + std::get<0>(cur) = flux::last(get_base<0>(self)); + return cur; + } } template diff --git a/test/test_cartesian_power.cpp b/test/test_cartesian_power.cpp index e3428289..9f157d72 100644 --- a/test/test_cartesian_power.cpp +++ b/test/test_cartesian_power.cpp @@ -261,9 +261,24 @@ constexpr bool test_cartesian_power() static_assert(test_cartesian_power()); +// https://github.com/tcbrindle/flux/issues/177 +constexpr bool issue_177() +{ + auto seq = flux::cartesian_power<3>(flux::empty); + + STATIC_CHECK(seq.is_empty()); + STATIC_CHECK(seq.size() == 0); + STATIC_CHECK(seq.is_last(seq.first())); + STATIC_CHECK(seq.first() == seq.last()); + + return true; +} +static_assert(issue_177()); + } TEST_CASE("cartesian power") { REQUIRE(test_cartesian_power()); + REQUIRE(issue_177()); } diff --git a/test/test_cartesian_product.cpp b/test/test_cartesian_product.cpp index 8deeba4a..478e0cc8 100644 --- a/test/test_cartesian_product.cpp +++ b/test/test_cartesian_product.cpp @@ -509,6 +509,20 @@ void issue_167() REQUIRE_THROWS_AS(flux::size(prod), flux::unrecoverable_error); } +// https://github.com/tcbrindle/flux/issues/177 +constexpr bool issue_177() +{ + auto seq = flux::cartesian_product(std::array{1, 2, 3}, flux::empty); + + STATIC_CHECK(seq.is_empty()); + STATIC_CHECK(seq.size() == 0); + STATIC_CHECK(seq.is_last(seq.first())); + STATIC_CHECK(seq.first() == seq.last()); + + return true; +} +static_assert(issue_177()); + } TEST_CASE("cartesian_product") @@ -516,4 +530,5 @@ TEST_CASE("cartesian_product") REQUIRE(test_cartesian_product()); issue_167(); + REQUIRE(issue_177()); }