Думаю, вас здесь многое смущает.
Во-первых, идеальная пересылка не имеет ничего общего с вариативными шаблонами. Вы можете создать класс-оболочку, у которого есть функция, которая принимает один аргумент и пересылает его в завернутый объект:
template<typename T>
struct Wrapper {
template<typename Arg>
decltype(auto) test(Arg&& arg) {
return t.test(std::forward<Arg>(arg));
}
T t;
};
Обратите внимание на то, что здесь используется идеальная переадресация без вариативных шаблонов. Если t.test
потребует в качестве параметра тип только для перемещения, его невозможно будет вызвать без forward<Arg>(arg)
.
Второе, что здесь происходит, - это параметр, за которым не следует &&
. Добавление &&
к ArgTypes
было бы ошибкой и могло бы привести к сбою компиляции в некоторых случаях. Рассмотрим этот простой случай:
std::function<void(int)> f;
int i = 0;
f(i);
Это не скомпилируется. Если вы добавите &&
к ArgTypes
, все параметры, которые не являются ссылочными (например, int
), станут ссылкой на rvalue в операторе вызова (в нашем случае int&&
). Поскольку все типы параметров уже правильно определены в списке аргументов std::function
, вы хотите получить в операторе вызова именно эти типы, а не преобразованные.
Почему вам нужен std::forward
, если вы не используете &&
? Потому что, даже если вам не нужно выводить категории значений, вам все равно не нужно копировать все аргументы в содержащуюся функцию. Если один из параметров std::function
равен int&
, вы не хотите его перемещать. Но если один из параметров std::unique_ptr<int>
, вы должны его переместить! И это именно то, для чего нужен std::forward
. Перемещается только то, что следует переместить.
person
Guillaume Racicot
schedule
05.03.2017
Ret, ArgTypes
уже исправлены - person Gabriel   schedule 05.03.2017