[libcxx-commits] [PATCH] D54410: [libc++] Add C++17 deduction guides for std::function
Arthur O'Dwyer via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 17 07:47:26 PDT 2019
Quuxplusone added inline comments.
================
Comment at: libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp:28
+int main() {
+ std::function f = f0{}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
+}
----------------
ldionne wrote:
> Quuxplusone wrote:
> > FWIW, this line has undefined behavior (or is IFNDR) — the standard doesn't define the behavior when the deduction guide participates in overload resolution but `decltype(&T::operator())` is not of the expected form.
> >
> > Maybe that means this test ought to go into `test/libcxx/` instead of `test/std/`. Maybe we don't care. I think all of the Big 3 implementations do the same thing in this case.
> I'm not sure I understand what you mean. You mean that because there's no deduction guide handling the rvalue-ref-qualified-call-operator case, it's ill-formed NDR? What I could find is http://eel.is/c++draft/function.objects#func.wrap.func.con-12:
>
>
> > ```
> > template<class F> function(F) -> function<see below>;
> > ```
> >
> > *Remarks*: This deduction guide participates in overload resolution only if `&F::operator()` is well-formed when treated as an unevaluated operand. In that case, if `decltype(&F::operator())` is of the form `R(G::*)(A...) cv_opt & noexcept_opt` for a class type `G`, then the deduced type is `function<R(A...)>`.
>
> So what you're saying is that since we don't say what happens when `decltype(&F::operator())` is *not* of the form `R(G::*)(A...) cv_opt & noexcept_opt` (in this case it's of the form `R(G::*)(A...) cv_opt && noexcept_opt`), the behaviour's undefined? I think I agree with that, however I think that's a LWG issue right here -- it should instead say something like:
>
> > ```
> > template<class F> function(F) -> function<see below>;
> > ```
> >
> > *Remarks*: This deduction guide participates in overload resolution only if `&F::operator()` is well-formed when treated as an unevaluated operand, and is of the form `R(G::*)(A...) cv_opt & noexcept_opt` for a class type `G`. In that case, the deduced type is `function<R(A...)>`.
>
> This would make the deduction guide NOT participate in overload resolution if it doesn't have the right form, which is effectively how it's implemented right now. And that mandates a compiler error. Do you agree with me?
>
Yes, I agree with your analysis. It's currently UB; it probably merits an LWG issue to make it not-UB; and almost certainly the right resolution (to the paper issue, //and// for vendors to use in practice until then) is to make the deduction guide not-participate-in-overload-resolution in the offending cases.
To verify the implementation of that resolution, you'd add a test case like this:
```
struct A : std::function<int(double)> {
int operator()() &&;
};
auto x = &A::operator(); // OK
std::function f = A(); // OK, guide doesn't participate in overload resolution, so we deduce from the move-constructor instead
static_assert(std::is_same_v<decltype(f), std::function<int(double)>>);
```
Which, it occurs to me, also exercises the part of the compiler that generates implicit candidates for copy- and move-constructors in the absence of any definition for the primary template. Isn't CTAD //fun?// 😛
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D54410/new/
https://reviews.llvm.org/D54410
More information about the libcxx-commits
mailing list