Open dhollman opened 6 years ago
I'd go even further and require only that the type can be destructured using structured bindings - I understand how this can be controversial, though.
Unless we actually need this for something, this sounds like a good thing to just leave up to L(E)WG since they will probably have opinions. std::pair
is the simplest thing we can say, so my default opinion is to just leave it as that for now.
I think the important take-away from what David says is we may not know what we need at this point, which is why we shouldn't make the concept actually require a std::pair
(and instead, a concept that is fulfilled by std::pair
.) This is strictly additive to the paper, but much less limiting on executor authors.
@RedBeard0531 I do already have some specific reasons for this. For instance, in my implementation sketches, I've found it useful to attach a invoke_then_execute()
function for cases when the concrete type of both the "destination" executor and the future type are known at construction time, but not the closure to pass to then execute (and the object requesting the promise contract needs to use polymorphic storage). There may also be some value in type-erasing the "source" executor at that same point, or even the closure itself (if available), to interoperate with non-ThenExecutor
s. I haven't fully convinced myself this is necessary (and thus it isn't in V1 of the paper), but I don't want to be locked out of it by our design.
I'd also appreciate the flexibility of not having to return a particular type from this property. My own executors would probably choose to return a tuple-like type spelled differently than std::pair
.
@jaredhoberock I'm glad you brought it up and not me. I was going to mention the case of std::pair
being unavailable on the hardware in question, but I'm often accused of resorting to this concern too often.
@dhollman Yes, there's the issue that some Standard Library components will not be available to all executors. However, another issue worth considering is that some authors might prefer to define a promise contract type which is more elaborate than a std::pair
and which may contain additional interfaces beyond .first
and .second
.
@jaredhoberock exactly my point :-)
@griwes Sure, but it isn't like this paper is going to be merged in tomorrow. This is still proposed wording that hasn't been chewed on by L(E)WG and will likely see some modifications by them anyway. Given that my default position is KISS. I'd focus on simplicity for ease of reading and understanding both by us and the rest of the committee. Every unnecessary sentence (and decay_t...) cuts against that. This paper is already somewhat long to read all at once.
@dhollman fair enough. I'm curious what kind of hardware can't support std::pair<T,U> given that it is defined as struct pair { T first; U second; };
, but I'll take your word for it.
Just to be clear, I'm not opposed to any complexity, I just want to ensure it is justified. This sounds like it may be justified.
@RedBeard0531 std::pair
is way more complex than you're giving it credit for. It has been said that std::pair
is "right on the edge of what we can express with C++" (can't find the source of the quote now, but I've heard several people say it). And yes, such an architecture does exist. At least at times in its history (now included?), CUDA hasn't supported the standard library, for instance.
@dhollman are you sure that was said about pair
rather than tuple
. This is the whole definition of pair
. It is required to be implemented as a simple struct with two elements. This is an observable fact due to StandardLayout. tuple
is really complicated though...
@RedBeard0531 I'm pretty sure it was pair
. The complexity arises from the constructors. There's a lot of nastiness hidden by that EXPLICIT
specification macro IIRC. Anyway, this is a bit beside the point. My main point was Jared's point that you might want to add some members for use outside of generic context (and that we might want to add some members to the generic concept at some point)
I think we should specify the
promise_contract_t
return type in terms of members (currentlyfirst
andsecond
, but I think we can do better than that) rather than strictly constraining it to be a specialization ofstd::pair
(maybe we haven't said this explicitly yet, but it does feel like this is implied). In the case of the polymorphic return type, this means we'd have to specify a relatively trivial concrete type, but I think that's fine.One of the main reasons to do this is that I can see us wanting to add traits or other functionality to the return type that don't really belong on the
promise
part or on thefuture_token
part, and if we have apair
as the means of binding these things together, we're kind of stuck. It's pretty similar to the logic behind providing a passthroughon_value()
function in this respect.