Рассмотрим этот код:
template<typename T>
void foo(T&& param){ //In this case && is called universal reference
std:string tmp = std::forward<string>(param);
}
У меня вопрос, если универсальный ссылочный тип может быть выведен, почему мне все еще нужно переадресовать?
Почему без пересылки tmp правильный c’or не будет вызван, даже если был выведен тип T.
Мой второй вопрос о правилах свертывания ссылок:
A& &&
становится A&
A&& &&
становится A&&
поэтому в соответствии с этими правилами и с учетом универсальной ссылки, подпись std :: forward не может быть следующей:
template<class T>
T&& forward(T&& arg){
return static_cast<T&&>(arg);
}
По правилам сверху, если T
Типом является ссылка rvalue, он свернется в ссылку rvalue, если тип T является ссылкой lvalue, он свернется в ссылку lvalue.
Так почему std::forward
у меня есть две разные подписи одна для ссылки на lvalue и одна для ссылки на rvalue Я что-то упустил?
У меня вопрос, если универсальный ссылочный тип может быть выведен, почему мне все еще нужно переадресовать?
Потому что, как только вы дадите имя параметру param
это lvalue, даже если функция была вызвана с rvalue, поэтому она не будет перенаправлена как rvalue, если вы не используете forward<T>
Почему без пересылки tmp правильный c’or не будет вызван, даже если был выведен тип T.
Так как param
это значение. Чтобы восстановить категорию значения аргумента, переданного foo
вам нужно отбросить его обратно string&
или же string&&
это означает, что вам нужно знать тип T
был выведен как, и использовать forward
сделать актерский состав.
Так почему
std::forward
у меня есть две разные подписи одна для ссылки на lvalue и одна для ссылки на rvalue Я что-то упустил?
Это было изменено http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html
Есть много фоновой информации в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html а также http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html
Проблема с предложенной вами версией заключается в том, что если вы скажете forward<string>
тогда параметр T
не выводится, поэтому не функционирует как ссылка для пересылки, а это означает, что T&&
не может связываться с lvalue, и он должен иметь возможность связываться с lvalue для того, чтобы forward<string>(param)
работать, потому что param
это значение там.