Reputation: 10911
I've been told here that the differences between these two signatures is not lvalue/rvalue related.
#include <iostream>
template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(*&& /*function*/)(ARGs...))
{
std::cout << "RValue function" << std::endl;
}
template <typename RET_TYPE, typename...ARGs>
void takeFunction(RET_TYPE(*& /*function*/)(ARGs...))
{
std::cout << "LValue function" << std::endl;
}
void function()
{
}
int main()
{
void(*f)() = function;
takeFunction(&function);
takeFunction(f);
return 0;
}
But if not that, then what is the difference that it is matching on?
Upvotes: 2
Views: 191
Reputation: 137315
There's a difference between a function and a pointer to function.
Functions are different because they are not objects (in the standardese sense of the word). There is no such thing as function rvalues (outside of certain weird cases involving non-static member functions). In fact, rvalue references to function are lvalues whether named or not.
Pointers to functions are, well, pointers, which are objects. You can have a prvalue of pointer to function type, or an xvalue of pointer to function type, or an lvalue of pointer to function type. &function
creates a prvalue pointer to function; in void (*f)() = function;
, the function-to-pointer conversion is applied to convert the function lvalue function
to a prvalue pointer to function, with which f
is initialized.
Now consider this set of overloads:
template <typename RET_TYPE, typename...ARGs>
void takeFunctionRef(RET_TYPE(&& /*function*/)(ARGs...)) // #1
{
std::cout << "RValue function" << std::endl;
}
template <typename RET_TYPE, typename...ARGs>
void takeFunctionRef(RET_TYPE(& /*function*/)(ARGs...)) // #2
{
std::cout << "LValue function" << std::endl;
}
takeFunctionRef(function); // calls #2
takeFunctionRef(std::move(function)); // still calls #2!
Overload #2 is selected because of a special tiebreaker in [over.ics.rank], bullet 3.1.4 that favors binding an lvalue reference to a function lvalue over binding an rvalue reference to a function lvalue. But both will bind successfully (i.e., if you remove #2, you'll see #1 called in both cases).
Upvotes: 3
Reputation: 14967
RET_TYPE(*&& /*function*/)(ARGs...)
is an rvalue reference to a function pointer.
RET_TYPE(*& /*function*/)(ARGs...)
is an lvalue reference to a function pointer.
&function
creates an rvalue temporary function pointer. So takeFunction(&function);
resolves to RET_TYPE(*&& /*function*/)(ARGs...)
.
void(*f)() = function;
defines a named lvalue function pointer. So takeFunction(f);
resolves to RET_TYPE(*& /*function*/)(ARGs...)
.
Besides this lvalue/rvalue difference, there is no other differences to these two functions.
Upvotes: 1