Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add examples and explanation on when tag_fallback/priority are useful #5208

Merged
merged 1 commit into from Feb 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -13,8 +13,8 @@ namespace hpx { namespace functional {
/// The `hpx::functional::tag_fallback_invoke` name defines a constexpr object
/// that is invocable with one or more arguments. The first argument
/// is a 'tag' (typically a CPO). It is only invocable if an overload
/// of tag_invoke() that accepts the same arguments could be found via
/// ADL.
/// of tag_fallback_invoke() that accepts the same arguments could be
/// found via ADL.
///
/// The evaluation of the expression
/// `hpx::functional::tag_fallback_invoke(tag, args...)` is
Expand Down Expand Up @@ -202,8 +202,34 @@ namespace hpx { namespace functional {
typename tag_fallback_invoke_result<Tag, Args...>::type;

///////////////////////////////////////////////////////////////////////////
// helper base class implementing the tag_invoke logic for CPOs that fall
// back to directly invoke its fallback
/// Helper base class implementing the tag_invoke logic for CPOs that fall
/// back to directly invoke its fallback.
///
/// This base class is in many cases preferable to the plain tag base class.
/// With the normal tag base class a default, unconstrained, default
/// tag_invoke overload will take precedence over user-defined tag_invoke
/// overloads that are not perfect matches. For example, with a default
/// overload:
///
/// template <typename T> auto tag_invoke(tag_t, T&& t) {...}
///
/// and a user-defined overload in another namespace:
///
/// auto tag_invoke(my_type t)
///
/// the user-defined overload will only be considered when it is an exact
/// match. This means const and reference qualifiers must match exactly, and
/// conversions to a base class are not considered.
///
/// With tag_fallback one can define the default implementation in terms of
/// a tag_fallback_invoke overload instead of tag_invoke:
///
/// template <typename T> auto tag_fallback_invoke(tag_t, T&& t) {...}
///
/// With the same user-defined tag_invoke overload, the user-defined
/// overload will now be used if is a match even if isn't an exact match.
/// This is because tag_fallback will dispatch to tag_fallback_invoke only
/// if there are no matching tag_invoke overloads.
template <typename Tag>
struct tag_fallback
{
Expand Down
Expand Up @@ -14,8 +14,8 @@ namespace hpx { namespace functional {
/// The `hpx::functional::tag_override_invoke` name defines a constexpr object
/// that is invocable with one or more arguments. The first argument
/// is a 'tag' (typically a CPO). It is only invocable if an overload
/// of tag_invoke() that accepts the same arguments could be found via
/// ADL.
/// of tag_override_invoke() that accepts the same arguments could be
/// found via ADL.
///
/// The evaluation of the expression
/// `hpx::functional::tag_override_invoke(tag, args...)` is
Expand Down Expand Up @@ -204,9 +204,18 @@ namespace hpx { namespace functional {
typename tag_override_invoke_result<Tag, Args...>::type;

///////////////////////////////////////////////////////////////////////////
// Helper base class implementing the tag_invoke logic for CPOs that allow
// overriding user-defined tag_invoke overloads with tag_override_invoke,
// and that allow setting a fallback with tag_fallback_invoke.
/// Helper base class implementing the tag_invoke logic for CPOs that allow
/// overriding user-defined tag_invoke overloads with tag_override_invoke,
/// and that allow setting a fallback with tag_fallback_invoke.
///
/// This helper class is otherwise identical to tag_fallback, but allows
/// defining an implementation that will always take priority if it is
/// feasible. This is useful for example in cases where a member function
/// should always take priority over any free function tag_invoke overloads,
/// when available, like this:
///
/// template <typename T>
/// auto tag_override_invoke(T&& t) -> decltype(t.foo()){ return t.foo(); }
template <typename Tag>
struct tag_priority
{
Expand Down
Expand Up @@ -219,12 +219,6 @@ namespace hpx { namespace parallel { inline namespace v1 {
// The segmented iterators we support all live in namespace hpx::segmented
namespace hpx { namespace segmented {

// Note: The implementation of the non-segmented algorithms relies on
// tag_fallback_invoke. For this reason the tag_invoke overloads here
// take precedence over the non-segmented algorithms. This has the
// advantage that the non-segmented algorithms do not need to be
// explicitly disabled for segmented iterators.

// clang-format off
template <typename InIter,
typename F,
Expand Down