[libcxx-commits] [PATCH] D54410: [libc++] Add C++17 deduction guides for std::function

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 17 11:33:39 PDT 2019


ldionne marked an inline comment as done.
ldionne 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'}}
+}
----------------
Quuxplusone wrote:
> 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?// 😛
I filed a LWG issue and CC'd you on the email.


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