Search code examples
c++move-semanticsrvalue-referenceforwarding-reference

Can `&&` inside a higher order function parameter be a forwarding reference?


The canonical example of a forwarding (or universal reference) goes like so:

template<typename T>
void f(T&& param); 

i.e.

"If a variable or parameter is declared to have type T&& for some deduced type T, that variable or parameter is a universal reference."

But consider a more contrived example:

 #include <iostream>

 class MyClass
 {
     int _val;

   public:
     void set_val(int &&newVal)
     {
         _val = newVal;
         std::cout << "New val = " << _val << std::endl;
     }
 };

 template <class T, class V> void evoke(void (T::*method)(V &&))
 // The && appears inside the context of a function type  ^^^^ argument
 {
     T obj;
     (obj.*method)(2);
 }

 int main()
 {
     evoke(&MyClass::set_val);
 }

In such cases I find it puzzling to follow the aforementioned rule. V is certainly deduced, but not on its own. Even though it's not a forwarding reference in the example above, can such constructs (function or member function pointer parameters) produce a forwarding reference for their arguments? Does the rule still apply in such cases?


Solution

  • No.

    From cppreference (emphasize mine):

    Forwarding references are a special kind of references that preserve the value category of a function argument, making it possible to forward it by means of std::forward. Forwarding references are either:

    1. function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template:

    [... examples ...]

    1. auto&& except when deduced from a brace-enclosed initializer list:

    [... more examples ...]

    For what its worth, the relevant section in the standard is [temp.deduct.call]. My standardese is not fluent, but to my understanding the description on cppreference (must be parameter of a function template) is accurate.