From fb4eb379ca0c1239e898e77c23b34265b82b258a Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Tue, 30 Jan 2018 00:13:54 +0100 Subject: [PATCH] More constexpr conversions --- include/continuable/detail/composition.hpp | 81 +++++++++++++--------- include/continuable/detail/traits.hpp | 26 ++++--- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/include/continuable/detail/composition.hpp b/include/continuable/detail/composition.hpp index 38a324b..e120b24 100644 --- a/include/continuable/detail/composition.hpp +++ b/include/continuable/detail/composition.hpp @@ -333,7 +333,7 @@ auto make_all_result_submitter(Callback&& callback, /// A callable object to merge multiple signature hints together struct entry_merger { template - constexpr auto operator()(T&... entries) noexcept { + constexpr auto operator()(T&... entries) const noexcept { return traits::merge(hints::hint_of(traits::identity_of(entries))...); } }; @@ -400,37 +400,53 @@ auto make_any_result_submitter(Callback&& callback) { std::forward(callback)); } -template -constexpr T first_of(traits::identity) noexcept; +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!"); +}; -template -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. - traits::static_for_each_in(traits::identity{}, [&](auto rest) { - auto is_empty = - (traits::pack_size_of(rest) == traits::size_constant_of<0>()); - static_assert(is_empty.value, "Expected all continuations to have the same" - "count of arguments!"); - }); - return signature; -} +/// A callable object to determine the shared result between all continuations +struct determine_shared_result { + template + constexpr auto operator()(T&... args) const noexcept { + return common_result_of(hints::signature_hint_tag<>{}, + hints::hint_of(traits::identity_of(args))...); + } -/// 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 -constexpr auto common_result_of(Signature signature, First first, - Args... args) { - using Common = - traits::identity>; +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. + std::initializer_list{0, ((void)check_pack_empty{}, 0)...}; + return signature; + } - return common_result_of(traits::push(signature, Common{}), - traits::pop_first(first), traits::pop_first(args)...); -} + template + static constexpr T first_of(traits::identity) noexcept; + + /// 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 common_result_of(traits::push(signature, common_type{}), + traits::pop_first(first), + traits::pop_first(args)...); + } +}; /// Finalizes the any logic of a given composition template @@ -441,11 +457,8 @@ auto finalize_composition( auto composition = base::attorney::consume_data(std::move(continuation)); - // Determine the shared result between all continuations - auto signature = traits::unpack(composition, [](auto const&... args) { - return common_result_of(hints::signature_hint_tag<>{}, - hints::hint_of(traits::identity_of(args))...); - }); + constexpr auto signature = + traits::unpack(composition, determine_shared_result{}); return base::attorney::create( [composition = std::move(composition)](auto&& callback) mutable { diff --git a/include/continuable/detail/traits.hpp b/include/continuable/detail/traits.hpp index 4deaf54..251e77a 100644 --- a/include/continuable/detail/traits.hpp +++ b/include/continuable/detail/traits.hpp @@ -203,6 +203,18 @@ constexpr auto static_if_impl(std::false_type, Type&& type, FalseCallback&& falseCallback) { return std::forward(falseCallback)(std::forward(type)); } + +/// Applies the given callable to all objects in a sequence +template +struct apply_to_all { + C callable; + + template + constexpr void operator()(T&&... args) { + (void)std::initializer_list{ + 0, ((void)callable(std::forward(args)), 0)...}; + } +}; } // namespace detail /// Returns the pack size of the given type @@ -340,22 +352,20 @@ constexpr auto unpack(F&& firstSequenceable, S&& secondSequenceable, } /// Applies the handler function to each element contained in the sequenceable +// TODO Maybe crashes MSVC in constexpr mode template constexpr void static_for_each_in(Sequenceable&& sequenceable, Handler&& handler) { - unpack( - std::forward(sequenceable), [&](auto&&... entries) mutable { - // Apply the consume function to every entry inside the pack - (void)std::initializer_list{ - 0, ((void)handler(std::forward(entries)), 0)...}; - }); + unpack(std::forward(sequenceable), + detail::apply_to_all>{ + std::forward(handler)}); } /// Adds the given type at the back of the left sequenceable template constexpr auto push(Left&& left, Element&& element) { - return unpack(std::forward(left), [&](auto&&... leftArgs) { - return std::make_tuple(std::forward(leftArgs)..., + return unpack(std::forward(left), [&](auto&&... args) { + return std::make_tuple(std::forward(args)..., std::forward(element)); }); }