From 588ef04c747cbaa19d89290efae88c25ad576209 Mon Sep 17 00:00:00 2001 From: Tristan Brindle Date: Mon, 9 Dec 2024 11:31:03 +0000 Subject: [PATCH] Flatten: avoid hard error with non-sequence inner Sequence flatten requires both outer and inner to be sequences --- include/flux/adaptor/flatten.hpp | 1 + test/test_flatten.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/flux/adaptor/flatten.hpp b/include/flux/adaptor/flatten.hpp index 85a9e8f3..bddfa229 100644 --- a/include/flux/adaptor/flatten.hpp +++ b/include/flux/adaptor/flatten.hpp @@ -37,6 +37,7 @@ struct flatten_adaptor : inline_iter_base> { }; template + requires sequence> struct flatten_adaptor : inline_iter_base> { private: using InnerSeq = element_t; diff --git a/test/test_flatten.cpp b/test/test_flatten.cpp index b3ac0090..b4046cd8 100644 --- a/test/test_flatten.cpp +++ b/test/test_flatten.cpp @@ -28,13 +28,16 @@ * * the element type of the outer sequence is a reference type * * the inner sequence is multipass * - * Otherwise, the single-pass version is used. + * Otherwise, the single-pass version is used when the outer and + * the inner are both sequences, else the basic iterable version + * is used. */ namespace { constexpr bool test_flatten_iterable() { + // Outer is iterable only { std::array, 3> arr{ std::array{1, 2, 3}, @@ -49,6 +52,30 @@ constexpr bool test_flatten_iterable() using F = decltype(flattened); static_assert(flux::iterable); static_assert(flux::iterable); + static_assert(not flux::sequence); + + STATIC_CHECK(flattened.all(flux::pred::positive)); + STATIC_CHECK(check_equal(flattened, {1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + + // Outer is multipass, inner is iterable only + { + std::array, 3> arr{ + std::array{1, 2, 3}, + {4, 5, 6}, + {7, 8, 9} + }; + + auto views = flux::map(arr, [](auto inner) { + return std::views::transform(std::move(inner), std::identity{}); + }); + + auto flattened = flux::ref(views).flatten(); + + using F = decltype(flattened); + static_assert(flux::iterable); + static_assert(flux::iterable); + static_assert(not flux::sequence); STATIC_CHECK(flattened.all(flux::pred::positive)); STATIC_CHECK(check_equal(flattened, {1, 2, 3, 4, 5, 6, 7, 8, 9}));