Home > Net >  std::invoke with ref qualifiers
std::invoke with ref qualifiers

Time:08-01

I'm running into the following issue when using ref qualifiers with operator() below. What is the correct syntax to enable the l-value ref overload in this instance?

#include <functional>

struct F { 
   void operator()() &  {}
   void operator()() && {} // Commenting this overload enables code to compile
};

int main() { 
   F f;
   std::invoke(&F::operator(), f); 
}

Error

<source>: In function 'int main()':
<source>:10:15: error: no matching function for call to 'invoke(<unresolved overloaded function type>, F&)'
   10 |    std::invoke(&F::operator(), f);
      |    ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-trunk-20220731/include/c  /13.0.0/functional:107:5: note: candidate: 'template<class _Callable, class ... _Args> constexpr std::invoke_result_t<_Fn, _Args ...> std::invoke(_Callable&&, _Args&& ...)'
  107 |     invoke(_Callable&& __fn, _Args&&... __args)
      |     ^~~~~~
/opt/compiler-explorer/gcc-trunk-20220731/include/c  /13.0.0/functional:107:5: note:   template argument deduction/substitution failed:
<source>:10:15: note:   couldn't deduce template parameter '_Callable'
   10 |    std::invoke(&F::operator(), f);
      |    ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:10:15: error: no matching function for call to 'invoke(<unresolved overloaded function type>, F&)'
   10 |    std::invoke(&F::operator(), f);
      |    ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-trunk-20220731/include/c  /13.0.0/functional:107:5: note: candidate: 'template<class _Callable, class ... _Args> constexpr std::invoke_result_t<_Fn, _Args ...> std::invoke(_Callable&&, _Args&& ...)'
  107 |     invoke(_Callable&& __fn, _Args&&... __args)
      |     ^~~~~~
/opt/compiler-explorer/gcc-trunk-20220731/include/c  /13.0.0/functional:107:5: note:   template argument deduction/substitution failed:
<source>:10:15: note:   couldn't deduce template parameter '_Callable'
   10 |    std::invoke(&F::operator(), f);
      |    ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
Execution build compiler returned: 1

CodePudding user response:

For the first argument of std::invoke, which is expected to be a pointer to a member function.

As per cppref:

A pointer to function may be initialized from an overload set which may include functions, function template specializations, and function templates, if only one overload matches the type of the pointer

cppref:

The parameter types and the return type of the function must match the target exactly, no implicit conversions are considered

In your case, &F::operator() can't be deduced, you need to provide the type explicitly.

std::invoke<void(F::*)()&>(&F::operator(), f);
std::invoke<void(F::*)()&&>(&F::operator(), std::move(f));

Demo

CodePudding user response:

Along the lines of the answer provided by @Nimrod, the following explicit cast works as well.

int main() { 
   F f;
   std::invoke(static_cast<void(F::*)()&>(&F::operator()), f); 
   std::invoke(static_cast<void(F::*)()&&>(&F::operator()), std::move(f)); 

}

  • Related