From b011479834dbcad8f2aebf13b91df05773c6e816 Mon Sep 17 00:00:00 2001 From: Damien L-G Date: Wed, 27 Dec 2023 21:32:38 -0500 Subject: [PATCH 1/2] Modernize callbacks compile-time introspection --- src/details/ArborX_Callbacks.hpp | 128 +++++++++++-------------------- 1 file changed, 43 insertions(+), 85 deletions(-) diff --git a/src/details/ArborX_Callbacks.hpp b/src/details/ArborX_Callbacks.hpp index 841c0c2f3..626380c73 100644 --- a/src/details/ArborX_Callbacks.hpp +++ b/src/details/ArborX_Callbacks.hpp @@ -39,32 +39,22 @@ struct PostCallbackTag struct DefaultCallback { - template - KOKKOS_FUNCTION void operator()(Query const &, Value const &value, - OutputFunctor const &output) const + template + KOKKOS_FUNCTION void operator()(Predicate const &, Value const &value, + OutputFunctor const &out) const { - output(value); + out(value); } }; -// archetypal expression for user callbacks -template -using InlineCallbackArchetypeExpression = - std::invoke_result_t; - -// legacy nearest predicate archetypal expression for user callbacks -template -using Legacy_NearestPredicateInlineCallbackArchetypeExpression = - std::invoke_result_t; - // archetypal alias for a 'tag' type member in user callbacks template using CallbackTagArchetypeAlias = typename Callback::tag; template struct is_tagged_post_callback - : std::is_same, - PostCallbackTag>::type + : Kokkos::is_detected_exact::type {}; // output functor to pass to the callback during detection @@ -99,72 +89,47 @@ void check_valid_callback(Callback const &callback, Predicates const &, using PredicateTag = typename AccessTraitsHelper::tag; using Predicate = typename AccessTraitsHelper::type; - static_assert(!(std::is_same{} && - Kokkos::is_detected< - Legacy_NearestPredicateInlineCallbackArchetypeExpression, - Callback, Predicate, OutputFunctorHelper>{}), + static_assert(!(std::is_same_v && + std::is_invocable_v>), R"error(Callback signature has changed for nearest predicates. See https://github.com/arborx/ArborX/pull/366 for more details. Sorry!)error"); static_assert(is_valid_predicate_tag::value && - Kokkos::is_detected>{}, + std::is_invocable_v>, "Callback 'operator()' does not have the correct signature"); static_assert( - std::is_void>>{}, + std::is_void_v>>, "Callback 'operator()' return type must be void"); } -// EXPERIMENTAL archetypal expression for user callbacks -template -using Experimental_CallbackArchetypeExpression = - std::invoke_result_t; - -// Determine whether the callback returns a hint to exit the tree traversal -// early. template -struct invoke_callback_and_check_early_exit_helper - : std::is_same>::type -{}; - -// Invoke a callback that may return a hint to interrupt the tree traversal and -// return true for early exit, or false for normal continuation. -template -KOKKOS_INLINE_FUNCTION - std::enable_if_t, std::decay_t, - std::decay_t>::value, - bool> - invoke_callback_and_check_early_exit(Callback &&callback, - Predicate &&predicate, - Primitive &&primitive) +KOKKOS_FUNCTION bool invoke_callback_and_check_early_exit(Callback &&callback, + Predicate &&predicate, + Primitive &&primitive) { - return ((Callback &&) callback)((Predicate &&) predicate, - (Primitive &&) primitive) == - CallbackTreeTraversalControl::early_exit; -} - -// Invoke a callback that does not return a hint. Always return false to -// signify that the tree traversal should continue normally. -template -KOKKOS_INLINE_FUNCTION - std::enable_if_t, std::decay_t, - std::decay_t>::value, - bool> - invoke_callback_and_check_early_exit(Callback &&callback, - Predicate &&predicate, - Primitive &&primitive) -{ - ((Callback &&) callback)((Predicate &&) predicate, (Primitive &&) primitive); - return false; + if constexpr (std::is_same_v>) + { + // Invoke a callback that may return a hint to interrupt the tree traversal + // and return true for early exit, or false for normal continuation. + return ((Callback &&) callback)((Predicate &&) predicate, + (Primitive &&) primitive) == + CallbackTreeTraversalControl::early_exit; + } + else + { + // Invoke a callback that does not return a hint. Always return false to + // signify that the tree traversal should continue normally. + ((Callback &&) callback)((Predicate &&) predicate, + (Primitive &&) primitive); + return false; + } } template @@ -179,29 +144,22 @@ void check_valid_callback(Callback const &callback, Predicates const &) static_assert(is_valid_predicate_tag::value, "The predicate tag is not valid"); - static_assert(Kokkos::is_detected{}, + static_assert(std::is_invocable_v, "Callback 'operator()' does not have the correct signature"); static_assert( - !(std::is_same{} || - std::is_same{}) || - (std::is_same< - CallbackTreeTraversalControl, - Kokkos::detected_t>{} || - std::is_void< - Kokkos::detected_t>{}), + !(std::is_same_v || + std::is_same_v) || + (std::is_same_v> || + std::is_void_v>), "Callback 'operator()' return type must be void or " "ArborX::CallbackTreeTraversalControl"); static_assert( - !std::is_same{} || - std::is_void< - Kokkos::detected_t>{}, + !std::is_same_v || + std::is_void_v>, "Callback 'operator()' return type must be void"); } From c697fadd15f89087e60d2583a73c0e090983e84b Mon Sep 17 00:00:00 2001 From: Damien L-G Date: Wed, 27 Dec 2023 21:52:26 -0500 Subject: [PATCH 2/2] Fixup const qualification for callback invocation --- src/details/ArborX_Callbacks.hpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/details/ArborX_Callbacks.hpp b/src/details/ArborX_Callbacks.hpp index 626380c73..8774bd778 100644 --- a/src/details/ArborX_Callbacks.hpp +++ b/src/details/ArborX_Callbacks.hpp @@ -90,19 +90,19 @@ void check_valid_callback(Callback const &callback, Predicates const &, using Predicate = typename AccessTraitsHelper::type; static_assert(!(std::is_same_v && - std::is_invocable_v>), R"error(Callback signature has changed for nearest predicates. See https://github.com/arborx/ArborX/pull/366 for more details. Sorry!)error"); static_assert(is_valid_predicate_tag::value && - std::is_invocable_v>, "Callback 'operator()' does not have the correct signature"); static_assert( - std::is_void_v>>, "Callback 'operator()' return type must be void"); } @@ -144,22 +144,25 @@ void check_valid_callback(Callback const &callback, Predicates const &) static_assert(is_valid_predicate_tag::value, "The predicate tag is not valid"); - static_assert(std::is_invocable_v, + static_assert(std::is_invocable_v, "Callback 'operator()' does not have the correct signature"); static_assert( !(std::is_same_v || std::is_same_v) || - (std::is_same_v> || - std::is_void_v>), + (std::is_same_v< + CallbackTreeTraversalControl, + std::invoke_result_t> || + std::is_void_v< + std::invoke_result_t>), "Callback 'operator()' return type must be void or " "ArborX::CallbackTreeTraversalControl"); static_assert( !std::is_same_v || - std::is_void_v>, + std::is_void_v< + std::invoke_result_t>, "Callback 'operator()' return type must be void"); }