Why don't C ++ lines need std :: forward to call the function you want?

I am learning std::forward . I wrote a short program to check what happens if we do not call std::forward before passing the arguments to another function call:

 #include <iostream> #include <typeinfo> #include <string> using namespace std; class Example { }; ostream &operator << (ostream &os, const Example &e) { os << "yes!"; return os; } void test_forward_inner(const Example &e) { cout << "& " << e << endl; } void test_forward_inner(Example &&e) { cout << "&& " << e << endl; } void test_forward_inner(const string &e) { cout << "& " << e << endl; } void test_forward_inner(string &&e) { cout << "&& " << e << endl; } template <typename T> void test_forward_wrapper(T &&arg) { test_forward_inner(arg); } int main() { Example e; test_forward_wrapper(e); test_forward_wrapper(Example()); cout << endl; string s("hello"); test_forward_wrapper(s); test_forward_wrapper("hello"); return 0; } 

Here I tried forwarding lvalue and rvalue from test_forward_wrapper() to test_forward_inner() . Running this program gives the result:

 & example & example & hello && hello 

For std::string s, the desired internal function was called, but for my own class, only the lvalue version was called. Only if I call std::forward before passing the arguments to the internal function can the rvalue version be called.

What is the difference here? As I know, in accordance with the rules for dropping links, when the shell was called using Example() , the value of rvalue T will be displayed as Example , and arg will be of type Example && , so the rvalue version should be called an internal function.

And for other situations, such as the case of std::string here, the correct version of the internal function was called, then can std::forward be deleted here? If not, what (maybe something bad) will happen?

+5
source share
2 answers

Note that "hello" not std::string , it is a const char[6] . And test_forward_wrapper() is a function template, the template argument T will be output as char const (&)[6] for it.

Inside test_forward_wrapper() , test_forward_inner() is called with const char[6] , which must first be converted to std::string . This is a temporary std::string , i.e. Rvalue, preferred by rvalue reference binding, so test_forward_inner(string &&) called.

Passing the exact std::string to test_forward_wrapper() will produce the same result.

 test_forward_wrapper(std::string("hello")); 
+7
source

The difference is that in

 test_forward_wrapper("hello"); 

hello here is not std::string . This is a const char * .

Change it to

 test_forward_wrapper(std::string("hello")); 

And the result will be the same as the user class.

+4
source

All Articles