Closed cor3ntin closed 1 year ago
F has the same trailing requires-clause as the function call operator, if any.
I don't think that works. A trailing requires-clause is not part of a function type (see dcl.fct), instead it is part of the syntax of init-declarator. Thus, there is not really such a thing as a "pointer to function with a trailing requires-clause".
In short, the answer to
It is unclear if the function returned by the conversion operator of a lambda is constrained.
is: The conversion operator does not return a function, but a pointer-to-function, and such pointer types cannot syntactically be constrained.
I'm not seeing a specification defect leading to the claimed lack of clarity.
I would be very surprised if the intent is for the example to be posted.
I think if we constrain F, it means that we cannot return it from the conversion operator, ie, taking its address would fail. But maybe constraining the conversion operator is more sensible then? I think your earlier reply suggested that.
After all, all of these should also probably be ill-formed
template<class T> void f() {
auto l = []() requires false { };
l.operator()(); //#1
l(); // #2
void(*ptr)() = l; // #3
}
template void f<int>();
Maybe. The point is that constraints guide overload resolution (only), and don't mess with the function type. Constrained lambdas are useful for a std::overloads
scenario, for example, and also for generic lambdas, I guess.
There is no evidence that the "constrained lambdas" feature was intended to affect the conversion to function pointer in any shape or form. (If I'm wrong, please point me to the relevant section in the corresponding paper once you've done the archeology.)
As such, I'm not seeing a CWG-level defect. If you believe the outcomes that you show are undesirable, feel free to suggest a change to EWG. (A trailing requires-clause can refer to the lambda's parameters, which are not in scope for the conversion operator, so I'm not seeing how this would work.)
There are a few options here:
This seems in need of an investigation and a design decision by EWG. I'm not going to create a CWG issue for a fishing expedition, if the existing wording is clear (although possibly the effects are undesirable).
It is unclear if the function returned by the conversion operator of a lambda is constrained.
[expr.prim.lambda.closure]/p8 states
Consider
Here the call operator has unsatisfied constraints. And while
#1
is clearly ill-formed, is#2
also ill-formed? Indeed, if the call operator is not a valid candidate, then overload resolution will consider the conversion operator to function pointer in order to perform a surrogate call.Presumably,
#2
should be ill-formed, so we need a way to preserve the constraints.Note that while investigating this, i did question whether calls to lambda expressions should consider their conversion operators but previous discussion suggest that it might be observable? https://lists.isocpp.org/ext/2021/12/18749.php
Suggested resolution