Попытка №2, в первой был бред:
Основной проблемой является то, что внутри метода все параметры имеют тип l-value. То есть модификатор параметра && - это лишь требование, чтобы на место этого аргумента вызывающий код передал r-value (а для шаблонов даже этого не требует, благодаря склейки ссылок). И раз так, то ваш метод my_forward переделает вернёт l-value ссылки вообще для всех аргументов.
Отсюда берётся необходимость явно указывать тип аргумента - чтобы использовался именно выведенный тип, а не l-value на этот тип. Ну и почему 2 специализации: если указать явно тип аргумента и явно специализировать функцию каким-нибудь r-value, то my_forward будет ожидать строго r-value, и являющееся l-value значение параметра туда не подойдёт.
В объяснение моих мыслей, код
#include <iostream>
template<typename T>
decltype(auto) my_forward(T&& arg)
{
return static_cast<T&&>(arg);
}
template <typename T, typename K>
void forward(T&& t, K&& k)
{
std::cout << std::is_same<int&&, decltype(my_forward(t))>::value << std::endl;
std::cout << std::is_same<int&, decltype(my_forward(k))>::value << std::endl;
std::cout << std::is_same<int&&, decltype(std::forward<T>(t))>::value << std::endl;
std::cout << std::is_same<int&, decltype(std::forward<K>(t))>::value << std::endl;
}
int main()
{
int lval = 10;
forward(10, lval);
return 0;
}
вернёт
0
1
1
1
То есть предположение что my_forward вернуло int&& для первого параметра - не верно!