This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.

### 2767. `not_fn call_wrapper` can form invalid types

Section: 20.14.13 [func.not.fn] Status: C++17 Submitter: Jonathan Wakely Opened: 2016-08-19 Last modified: 2021-06-06

Priority: 0

View all issues with C++17 status.

Discussion:

The definition of the `call_wrapper` type in the C++17 CD means this fails to compile:

>     #include <functional>

>     struct abc { virtual void f() const = 0; };
>     struct derived : abc { void f() const { } };
>     struct F { bool operator()(abc&) { return false; } };
>     derived d;
>     bool b = std::not_fn(F{})(static_cast<abc&&>(d));

The problem is that the return types use `result_of_t<F(abc)>` and `F(abc)` is not a valid function type, because it takes an abstract class by value.

The return types should use `result_of_t<F(Args&&...)>` instead.

[2016-09-09 Issues Resolution Telecon]

P0; move to Tentatively Ready

Proposed resolution:

This wording is relative to N4606.

1. Modify [func.not_fn], class `call_wrapper` synopsis, as indicated:

   >     class call_wrapper
   >     {
   >       […]
   >       template<class... Args>
   >         auto operator()(Args&&...) &
   >           -> decltype(!declval<result_of_t<FD&(Args&&...)>>());
   >       template<class... Args>
   >         auto operator()(Args&&...) const&
   >           -> decltype(!declval<result_of_t<FD const&(Args&&...)>>());
   >       template<class... Args>
   >         auto operator()(Args&&...) &&
   >           -> decltype(!declval<result_of_t<FD(Args&&...)>>());
   >       template<class... Args>
   >         auto operator()(Args&&...) const&&
   >           -> decltype(!declval<result_of_t<FD const(Args&&...)>>());
   >       […]
   >     };

2. Modify the prototype declarations of [func.not_fn] as indicated:

   >     template<class... Args>
   >       auto operator()(Args&&... args) &
   >         -> decltype(!declval<result_of_t<FD&(Args&&...)>>());
   >     template<class... Args>
   >       auto operator()(Args&&... args) const&
   >         -> decltype(!declval<result_of_t<FD const&(Args&&...)>>());

   > > […]

   >     template<class... Args>
   >       auto operator()(Args&&... args) &&
   >         -> decltype(!declval<result_of_t<FD(Args&&...)>>());
   >     template<class... Args>
   >       auto operator()(Args&&... args) const&&
   >         -> decltype(!declval<result_of_t<FD const(Args&&...)>>());