Std::forward и шаблонный тип удержания
Я написал следующую небольшую программу, чтобы понять, как работает std:: forward.
#include <iostream>
#include <memory>
template<class T>
void foo3(T&& bar){
std::cout<<"foo3&&"<<std::endl;
}
template<class T>
void foo3(T& bar){
std::cout<<"foo3&"<<std::endl;
}
template<class T>
void foo(T&& bar){
std::cout<<"foo&&"<<std::endl;
foo3(std::forward<T>(bar));
}
template<class T>
void foo(T& bar){
std::cout<<"foo&"<<std::endl;
foo3(std::forward<T>(bar));
}
int main(int argc, char * argv []){
int i = 1;
foo(2);
foo(i);
return 0;
}
Я ожидал бы следующий вывод:
"foo&&"
"foo3&&"
"foo&"
"foo3&"
Однако я получаю следующий результат, который не могу объяснить:
"foo&&"
"foo3&&"
"foo&"
"foo3&&"
Поэтому, если foo вызывается с lvalue, я ожидаю, что foo перешлет lvalue и вызовет версию looue foo3. Однако все время вызывается foo3(T&&). Я правильно понял, что std:: forward работает или есть небольшая ошибка? Или, что еще хуже, должен ли код работать так, как я ожидал, и, возможно, я испортил реализацию моего компилятора? Кстати, я использую G ++ 7,2
1 ответ
Я правильно понял, что работает std::forward
Да. std::forward
для пересылки ссылок, и bar
в void foo(T&)
не является. Если вы не уважаете это, вы получите странное поведение.
Чтобы понять, почему вам нужно понять, что std::forward
на самом деле Это просто актерский состав
static_cast<T&&>(t)
куда t
это аргумент std::forward
, Итак, последний звонок foo
выглядит так:
std::cout<<"foo&"<<std::endl;
foo3(std::forward<int>(bar));
T
выводится int
, и если посмотреть на актерский состав, вы увидите, что он кастует bar
на ссылку rvalue вместо ссылки lvalue, как вы ожидали.