2016-09-02 133 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

^(並且在這種情況下不衰減) –

相關問題