diff --git a/include/continuable/detail/composition-any.hpp b/include/continuable/detail/composition-any.hpp index 3a0fafe..59c25eb 100644 --- a/include/continuable/detail/composition-any.hpp +++ b/include/continuable/detail/composition-any.hpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -101,51 +102,61 @@ auto make_any_result_submitter(Callback&& callback) { std::forward(callback)); } -template -struct check_pack_empty { - static constexpr auto const is_empty = - (decltype(traits::pack_size_of(std::declval())){} == - traits::size_constant_of<0>()); - static_assert(is_empty.value, "Expected all continuations to have the same" - "count of arguments!"); -}; - -/// A callable object to determine the shared result between all continuations -struct determine_shared_result { - template - constexpr auto operator()(T&&...) const noexcept { - return common_result_of(hints::signature_hint_tag<>{}, - hints::hint_of(traits::identify())...); +struct result_deducer { + template + static auto deduce_one(std::false_type, traits::identity) { + static_assert(traits::fail::value, + "Non continuable types except tuple like and homogeneous " + "containers aren't allowed inside an any expression!"); + } + template + static auto deduce_one(std::true_type, traits::identity id) { + return hints::hint_of(id); + } + template + static auto deduce(traversal::container_category_tag, + traits::identity id) { + return deduce_one(base::is_continuable{}, id); } -private: - template - static constexpr auto common_result_of(Signature signature, - hints::signature_hint_tag<>, - Args... /*args*/) { - /// Assert that the other signatures are empty too which means all - /// signatures had the same size. - (void)std::initializer_list{0, ((void)check_pack_empty{}, 0)...}; - return signature; + /// Deduce a homogeneous container + template + static auto deduce(traversal::container_category_tag, + traits::identity) { + + // Deduce the containing type + using element_t = std::decay_t().begin())>; + return deduce(traversal::container_category_of_t{}, + traits::identity{}); } - template - static constexpr T first_of(traits::identity) noexcept; + template + static auto deduce_same_hints(First first, T...) { + static_assert(traits::conjunction...>::value, + "The continuables inside the given pack must have the " + "same signature hint!"); - /// Determine the common result between all continuation which are chained - /// with an `any` strategy, consider two continuations: - /// c1 with `void(int)` and c2 with `void(float)`, the common result shared - /// between both continuations is `void(int)`. - template - static constexpr auto common_result_of(Signature signature, First first, - Args... args) { - using common_type = - traits::identity>; + return first; + } - return common_result_of(traits::push(signature, common_type{}), - traits::pop_first(first), - traits::pop_first(args)...); + template + static auto deduce_tuple_like(std::integer_sequence, + traits::identity) { + + return deduce_same_hints(deduce( + traversal::container_category_of_t< + std::decay_t(std::declval()))>>{}, + traits::identity< + std::decay_t(std::declval()))>>{})...); + } + + /// Traverse tuple like container + template + static auto deduce(traversal::container_category_tag, + traits::identity id) { + + std::make_index_sequence::value> constexpr const i{}; + return deduce_tuple_like(i, id); } }; } // namespace any @@ -155,8 +166,9 @@ template <> struct composition_finalizer { template static constexpr auto hint() { - return decltype(traits::unpack(std::declval(), - any::determine_shared_result{})){}; + return decltype(any::result_deducer::deduce( + traversal::container_category_of_t>{}, + traits::identity>{})){}; } template diff --git a/include/continuable/detail/features.hpp b/include/continuable/detail/features.hpp index 03675d2..d1c10fc 100644 --- a/include/continuable/detail/features.hpp +++ b/include/continuable/detail/features.hpp @@ -54,6 +54,7 @@ #define CONTINUABLE_HAS_CXX17_CONSTEXPR_IF #define CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION #define CONTINUABLE_HAS_CXX17_DISJUNCTION + #define CONTINUABLE_HAS_CXX17_CONJUNCTION #else // Generic feature detection based on __has_feature #if defined(__has_feature) @@ -73,6 +74,7 @@ defined(__cpp_lib_experimental_logical_traits) && \ (__cpp_lib_experimental_logical_traits >= 201511) #define CONTINUABLE_HAS_CXX17_DISJUNCTION + #define CONTINUABLE_HAS_CXX17_CONJUNCTION #endif #endif diff --git a/include/continuable/detail/traits.hpp b/include/continuable/detail/traits.hpp index 7ff9d37..46e239a 100644 --- a/include/continuable/detail/traits.hpp +++ b/include/continuable/detail/traits.hpp @@ -472,6 +472,23 @@ template using disjunction = typename detail::disjunction_impl>::type; #endif // CONTINUABLE_HAS_CXX17_DISJUNCTION +#ifdef CONTINUABLE_HAS_CXX17_CONJUNCTION +using std::conjunction; +#else +namespace detail { +/// Declares a C++14 polyfill for C++17 std::conjunction. +template > +struct conjunction_impl : std::common_type {}; +template +struct conjunction_impl, + void_t...>> + : std::common_type {}; +} // namespace detail + +template +using conjunction = typename detail::conjunction_impl>::type; +#endif // CONTINUABLE_HAS_CXX17_CONJUNCTION + } // namespace traits } // namespace detail } // namespace cti diff --git a/test/playground/test-playground.cpp b/test/playground/test-playground.cpp index 4929417..43f6b89 100644 --- a/test/playground/test-playground.cpp +++ b/test/playground/test-playground.cpp @@ -124,7 +124,7 @@ void old() { int main(int, char**) { using namespace cti::detail; - cti::when_seq( + /*cti::when_seq( cti::make_ready_continuable(0, 1), 2, //< See this plain value std::vector>{cti::make_ready_continuable(3), cti::make_ready_continuable(4)}, @@ -167,5 +167,12 @@ int main(int, char**) { std::tuple> r5) { // ... util::unused(r0, r1, r2, r34, r5); + });*/ + + composition::apply_composition(composition::composition_strategy_any_tag{}, + cti::make_ready_continuable(22), + cti::make_ready_continuable(44)) + .then([](int) { + }); } diff --git a/test/unit-test/multi/test-continuable-connection-any.cpp b/test/unit-test/multi/test-continuable-connection-any.cpp index cfe17d6..c859bb8 100644 --- a/test/unit-test/multi/test-continuable-connection-any.cpp +++ b/test/unit-test/multi/test-continuable-connection-any.cpp @@ -57,12 +57,6 @@ TYPED_TEST(single_dimension_tests, is_logical_any_connectable) { ASSERT_ASYNC_TYPES(std::move(chain), tag1, tag2, tag3); } - { - using common = std::common_type_t; - auto chain = this->supply(char(0), int(0)) || this->supply(int(0), char(0)); - ASSERT_ASYNC_TYPES(std::move(chain), common, common); - } - { // Check the evaluation order unsigned i = 0;