Ответ 1
Идеальная переадресация работает только тогда, когда сама функция (в данном случае operator()
) построена шаблоном и выводятся аргументы шаблона. Для std::function
вы получаете типы аргументов operator()
из параметров шаблона самого класса, что означает, что они никогда не будут выводиться из любых аргументов.
Весь трюк за совершенной переадресацией - это часть вычитания аргумента шаблона, которая вместе со свертыванием ссылки является идеальной пересылкой.
Я просто позвоню на мой другой ответ о std::forward
здесь, где я объясню, как работает совершенная переадресация (и std::forward
).
Обратите внимание, что std::function
operator()
не нуждается в идеальной переадресации, так как сам пользователь решает, какие параметры должны быть. Это также является причиной, по которой вы не можете просто добавить &&
в operator()
; возьмите этот пример:
void foo(int){}
int main(){
// assume 'std::function' uses 'ArgTypes&&...' in 'operator()'
std::function<void(int)> f(foo);
// 'f 'operator()' will be instantiated as
// 'void operator()(int&&)'
// which will only accept rvalues
int i = 5;
f(i); // error
f(5); // OK, '5' is an rvalue
}