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
Further simplify tag_invoke helpers #5344
Comments
The The fallback and override facilities we have created go beyond what was intended for The main problem I see (as also pointed out by @K-ballo) is that having a That said, I still believe that our facilities ( |
The uses of In the future we can look into approaching the underlying problem differently. |
As a first step I'd suggest to add detection of
I agree wrt the segmented algorithms. However for customizing the algorithms for GPUs and/or datapar vectorization (both based on overloading the algorithms on the execution policy), the use of tag_invoke to implement overload resolution is right on the mark. So we're left with a situation where part of the desired overloads do actually 'customize' the algorithms (in the sense of p1895), and other overloads go beyond. In general, the capabilities enabled by |
I'm not sure I follow all of this. I see two points:
|
Segmented algorithms are actually overloads. They are not customizations (nor algorithms should be customization points).
Concepts would bring subsumption, some This would not work for algorithms as objects, as it applies to overloads. Algorithm objects would still have to dispatch to actual overloads for concepts to be advantageous for resolution. |
I am not familiar with those two, so I couldn't say. The fallback part in the snippet looks suspicious, with
|
Is this a theoretical or practical view, or both? Being able to do
Dispatch to
Fair enough. In short they're an overelaborate way of implementing exactly that override/fallback behaviour over here: hpx/libs/core/functional/include/hpx/functional/tag_priority_invoke.hpp Lines 288 to 325 in 6017158
if constexpr the operator() overloads are ordered using is_tag_x_invocable and sfinae. Overelaborate because there should be only one override or fallback, but the mechanism right now in principle allows for multiple overloads of the override/fallback. Users are, however, only meant to provide tag_invoke overloads.
Could you expand on why it looks suspicious? The example is essentially what's in P1895 "Strategies for defining default implementations of CPOs" section 1 and 2. The motivation for us to introduce Keep in mind my ignorance in how practical these kind of things are in reality in standard library implementations. Hence my question in the beginning about "theoretical or practical view", and I'm trying to understand where your concerns are. |
Frankly, this is exactly what we try to avoid. The main dispatch point above shouldn't be aware of the override implementations as those might not even be known ATM. All it should do is to dispatch to the proper override (based on overload resolution), which is exactly what our tag_fallback implementation does. |
Yeah, I definitely agree that this is not how one would go about this. |
My attempt at expanding was in the pseudo-code. The |
I'm not sure what the differences would be... A customization is a way for a type or a family of types to override some concept's implementation. It is a Algorithms aren't concepts, nor they are pieces of some larger concepts. They are not some interface's Segmented iterators are not a type. There is no namespace associated with all possible segmented iterators. Execution policies were designed as tags, to be used with traditional overloading. When doing tag dispatching, overloads must NOT be found by argument dependent lookup, since the tag and only the tag itself is used for dispatch, and no user defined argument that happens to be passed along should interfere with that. If the set of overloads that a call is being dispatched to is closed, then the overheads associated with the overloading machine can be avoided by taking advantage of constexpr-if. (*) While for algorithms as originally designed customization would defeat the purpose, there's something to consider after the introduction of range-based algorithms. For instance, |
Still, we need a single mechanism that helps handling both cases in a convenient way.
Our algorithm overloads are not a closed set. Let's not call the objects implementing the algorithms 'Customization Point Objects' but 'Dispatch Point Objects' (or something similar). I believe that if we do that, many of the issues discussed will be resolved. Instead of naming the dispatch points |
It's not possible to have a mechanism that does both exclusively ADL at the same time it avoids ADL entirely. |
I can agree with that these two things are mutually exclusive. However, I don't think we do need both ADL and non-ADL at the same time. What we need is ADL and tag dispatching together. This however shouldn't be problematic, as even the dispatching of |
I think we do not want ADL in general, except for the very specific case of customization. Many of the uses mentioned in here are not, in fact, customizations. For instance, there's no associated namespace for models of the segmented iterator in which to "customize" algorithms for them, nor a conceptual model of how these interact with executors in the case I want to "customize" an algorithm for my own concrete executor type without dropping segmented-ness on the floor. Neither of these sound like good fits for customization anyways. I'm convinced a better encompassing design can be reached by understanding all the use cases involved, and how they interact with each other. I don't think it can ever be a single mechanism, as some of the goals are mutually exclusive. I don't think it can just be |
I think we can close this as resolved. @K-ballo any objections? |
None from me. |
Related to #5332. @hkaiser, @K-ballo, I went back to wg21.link/p1895, and @K-ballo is very correct in saying that they did consider the fallback and override cases in the paper. The "Design Discussion" section contains the relevant parts. With #5283 we get a very viable alternative with
if constexpr
. Thetag*
base classes do help reduce boilerplate currently, so it'd be a shame to completely get rid of them, but being able to useif constexpr
would quite significantly simplify things without having to keep thefallback
/override
versions. Until we require C++17 I think they are a reasonable compromise though.The text was updated successfully, but these errors were encountered: