https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121055

            Bug ID: 121055
           Summary: [15/16 Regression] __is_invocable built-in doesn't
                    match std::invoke for rvalue-ref qualified member
                    function
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

#include <functional>

struct F
{
  void operator()() && { }
};

template<class T>
void test(T t)
{
  auto pmf = &T::operator();
  if constexpr (std::is_invocable_v<void (T::*)()&&,
std::reference_wrapper<T>>)
    std::invoke(pmf, std::ref(t));
}

int main()
{
  F f;
  test(f);
}


This compiles successfully with GCC 14 or with Clang+libstdc++, but fails with
GCC 15 and GCC 16 because is_invocable_v uses the new __is_invocable built-in.
The GCC built-in incorrectly returns true, so we try to do the std::invoke
call, which is ill-formed:

invoke.cc: In instantiation of 'void test(T) [with T = F]':
invoke.cc:19:7:   required from here
   19 |   test(f);
      |   ~~~~^~~
invoke.cc:13:16: error: no matching function for call to 'invoke(void (F::*&)()
&&, std::reference_wrapper<F>)'
   13 |     std::invoke(pmf, std::ref(t));
      |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
invoke.cc:13:16: note: there is 1 candidate
In file included from invoke.cc:1:
/home/jwakely/gcc/16/include/c++/16.0.0/functional:121:5: note: candidate 1:
'template<class _Callable, class ... _Args> std::invoke_result_t<_Callable,
_Args ...> std::invoke(_Callable&&, _Args&& ...)'
  121 |     invoke(_Callable&& __fn, _Args&&... __args)
      |     ^~~~~~
/home/jwakely/gcc/16/include/c++/16.0.0/functional:121:5: note: template
argument deduction/substitution failed:
In file included from /home/jwakely/gcc/16/include/c++/16.0.0/bits/move.h:37,
                 from
/home/jwakely/gcc/16/include/c++/16.0.0/bits/stl_function.h:60,
                 from /home/jwakely/gcc/16/include/c++/16.0.0/functional:51:
/home/jwakely/gcc/16/include/c++/16.0.0/type_traits: In substitution of
'template<class _Fn, class ... _Args> using std::invoke_result_t = typename
std::invoke_result::type [with _Fn = void (F::*&)() &&; _Args =
{std::reference_wrapper<F>}]':
/home/jwakely/gcc/16/include/c++/16.0.0/functional:121:5:   required by
substitution of 'template<class _Callable, class ... _Args>
std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&&
...) [with _Callable = void (F::*&)() &&; _Args = {std::reference_wrapper<F>}]'
invoke.cc:13:16:   required from 'void test(T) [with T = F]'
   13 |     std::invoke(pmf, std::ref(t));
      |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
invoke.cc:19:7:   required from here
   19 |   test(f);
      |   ~~~~^~~
/home/jwakely/gcc/16/include/c++/16.0.0/type_traits:3360:11: error: no type
named 'type' in 'struct std::invoke_result<void (F::*&)() &&,
std::reference_wrapper<F> >'
 3360 |     using invoke_result_t = typename invoke_result<_Fn,
_Args...>::type;
      |           ^~~~~~~~~~~~~~~


The built-in should not say it's invocable.

Reply via email to