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, как вы ожидали.

Другие вопросы по тегам