Я установил тестовый пример, чтобы узнать о идеальной пересылке.
std::string inner(const std::string& str ) {
return "const std::string&";
}
std::string inner(std::string& str ) {
return "std::string&";
}
std::string inner(const std::string&& str ) {
return "const std::string&&";
}
std::string inner(std::string&& str ) {
return "std::string&&";
}
template <typename T> void outer(T&& t) {
std::cout << "t: " << t << std::endl;
std::cout << "perfect forward: " << inner(std::forward<T>(t)) << std::endl;
std::cout << std::endl;
}
void PerfectForwarding()
{
outer("literal");
outer(lvalue);
outer(constlvalue);
outer(rvalue());
outer(constrvalue());
}
std::forward
работает так, как ожидалось. Интересное поведение возникает, когда я реализую свою собственную функцию прямого доступа без идентификации:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
Замена std::forward
на MyForward
во внешнем дает тот же результат! Поведение вызывает вопрос, почему используется идентификатор?
Компилятор VS2010
Обновление 1: в отношении предотвращения вычитания типа
AFAIK, правило вывода специального типа активируется только на T & &. Обратите внимание на определение forward, forward(typename identity<T>::type& t)
. Тип аргумента имеет только один &. Фактически, после того, как я изменил MyForward на использование идентификатора и не использовал кастинг (T & &), этот пример не компилируется. На первый взгляд, отливка от lvalue до rvalue, похоже, делает передовую работу.
Обновление 2: проверено на ideone.com с GCC 4.5, такое же поведение.