Passando uma referência a função como referência universal
Estou lutando para entender o que exatamente acontece ao passar uma referência a função para uma função como referência universal (que tipo está sendo deduzido). Vamos supor que temos uma função foo que usa um parâmetro como uma referência universal:
template<typename T>
void foo(T&& param)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
E então vamos fazer o seguinte:
void(&f)(int) = someFunction;
foo(f);
O resultado será:
void foo(T&&) [with T = void (&)int]
Isso é perfeitamente compreensível: estamos passando lvalue para nossa função foo, portanto o tipo deduzido é void (&) int, e o tipo do parâmetro será "void (&& &) int", que, sob as regras de colapso de referência, se torna nulo (& ) int. Param será apenas uma referência lvalue para uma função.
Mas quando eu faço o seguinte:
void(&f)(int) = someFunction;
foo(std::move(f));
foo imprimirá:
void foo(T&&) [with T = void (&)int]
que é exatamente o mesmo de antes! O que esta acontecendo aqui? Por que o resultado é o mesmo que ao passar lvalue? Eu esperaria que, uma vez que estamos passando rvalue para foo, o tipo deduzido deve ser T = void (int) e param deve se tornar void (&&) int. Isso sempre acontece com todos os outros tipos "normais" (como classes, tipos primitivos etc.) Por que é diferente ao lidar com referências de função?