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?
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:
- function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template:
[... examples ...]
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.