简体   繁体   中英

Std::forward and template type deduction

i have written the following little program to understand how std::forward works.

#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;
}

I would expect the following output:

"foo&&"
"foo3&&"
"foo&"
"foo3&"

However, I get the following result, which I can't explain:

"foo&&"
"foo3&&"
"foo&"
"foo3&&"

So if foo is invoked with an lvalue, I expect that foo will forward the lvalue and invoke foo3's lvalue version. However all the time foo3(T&&) is called. Did I understand something completely wrong about how std::forward works or is there a subtle bug? Or even worse, should the code work as I expected and maybe I messed up my compiler implementation? Btw.I'm using g++ 7.2

Did I understand something completely wrong about how std::forward works

Yes. std::forward is for forwarding references, and bar in void foo(T&) is not. If you don't respect this, you will get some strange behavior.

To understand why you'll need to understand what std::forward actually does. It is just a cast

static_cast<T&&>(t)

Where t is the argument to std::forward . So, the final call of foo looks like this:

std::cout<<"foo&"<<std::endl;
foo3(std::forward<int>(bar));

T is deduced to int , and if look at the cast, you'll see that it casts bar to an rvalue reference, instead of an lvalue reference like you expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM