2016-09-02 57 views
5

我在学习std::forward。我写了一个小程序来测试,如果我们不转发参数另一个函数调用之前调用std::forward会发生什么:为什么C++字符串不需要std :: forward来调用所需的函数?

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

在这里,我想一个左值和一个右值转发来自test_forward_wrapper()test_forward_inner()。运行此程序会输出:

& example 
& example 

& hello 
&& hello 

对于std::string S,目标内部函数被调用,但是对于我自己的类只有左值版本被调用。只有在将参数传递给内部函数之前调用std::forward才能调用右值版本。

这里的区别是什么?据我所知,根据参考折叠规则,当包装被调用Example()时,将推导出右值TExamplearg将具有类型Example &&因此应该调用内函数的右值版本。

而对于其他情况,如std::string这里的情况,调用了内部函数的正确版本,那么我们可以在这里删除std::forward?如果不是,会发生什么(可能是坏事)?

回答

7

请注意"hello"不是std::string,这是一个const char[6]。而test_forward_wrapper()是一个函数模板,模板参数T将被推断为char const (&)[6]

里面的test_forward_wrapper(),test_forward_inner()被称为const char[6],它需要首先转换为std::string。这是一个临时的std::string,即一个右值,最好是绑定到右值引用,这就是为什么test_forward_inner(string &&)被调用。

通过一个确切的std::stringtest_forward_wrapper()将得到相同的结果。

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

不同的是,在

test_forward_wrapper("hello"); 

“你好” 这里是不是std::string。这是一个const char *

更改为一个

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

而且结果会是一样的自定义类的。

+1

最重要的部分是,包装物为模板化(所以没有强迫在呼叫发生时),而内部功能不是,只接受'的std :: string',这意味着转化为'string'发生然后(为内部函数提供r值参考),不涉及转发。 – ShadowRanger

+3

'“hello”'不是'const char *',它是一个'const char [6]',可以衰减为'const char *'。 。 –

+1

^(并且在这种情况下不衰减) –

相关问题