2015-05-20 13 views
13

Próbuję zrozumieć odniesienia rvalue. Widziałem, jak są one wykorzystywane w konstruktorów, z rzeczy, jak std::move i std::forward, ale ja nadal nie rozumiem, dlaczego to nie działa:C++, odniesienia wartości r w parametrach funkcji

void func(string&& str) 
{ 
    cout << str << endl; 
} 
int main(int argc, char* argv[]) 
{ 
    string s("string"); 
    func(s); 
} 

I to robi:

template<typename T> 
void func(T&& str) 
{ 
    cout << str << endl; 
} 
int main(int argc, char* argv[]) 
{ 
    string s("string"); 
    func(s); 
} 

Dlaczego działa z wersją szablonu funkcji?

+4

Ta ostatnia wersja działa, ponieważ 'T' jest wydedukowana jako' string & '."Gdy typ parametru funkcji ma formę T && gdzie T jest parametrem szablonu, a argument funkcji jest lwartością typu A, typ A & jest używany do odliczenia argumentu szablonu." Użyj 'std :: move', jeśli chcesz by ten pierwszy działał. –

+0

Jest to szczególny przypadek potrącenia szablonu, tutaj (i tylko tutaj AFAIK), "T" można wywnioskować na typ odniesienia. Zwykle w dedukcji typu szablonu "T" jest wydedukowane jedynie jako brak odniesienia. –

+1

możliwy duplikat [Składni uniwersalnych odniesień] (http://stackoverflow.com/questions/14302849/syntax-for-universal-references) –

Odpowiedz

14

Jak @Peter powiedział, rodzaj T jest wyprowadzany jako string& i zasada odniesienia zawaleniem C++ 's mówi:

T & & ⇒ T & // z C++ 98
T & & & ⇒ T & // nowy dla C++ 0x
T & & & ⇒ T & // nowy dla C++ 0x
T & & & & ⇒ T & & // nowy dla C++ 0x

Więc func „s instancji jest rzeczywiście:

void func(string& str) 

I to działa.

6

Niektóre formalne wyjaśnienie oprócz użytkownika @ songyuanyao odpowiedź:

N4296::14.8.2.1 [temp.deduct.call]:

Szablon odliczenie argumentem odbywa się poprzez porównanie każdej funkcji typ parametru szablonu (nazwijmy go P) z typem odpowiedniego Argument połączenia (nazwij go A) zgodnie z opisem poniżej.

N4296::14.8.2.1/3 [temp.deduct.call]:

Odniesienie spedycja jest referencja RValue do CV-niewykwalifikowany szablonu parametr. Jeśli P jest odniesieniem do przekazywania przekazywania i , argumentem jest l-wartość, typ "lwartość odniesienie do A" stosuje się zamiast A do dedukcji typu.

Standard zapewnia również następujący przykład:

template <class T> int f(T&& heisenreference); 
template <class T> int g(const T&&); 
int i; 
int n1 = f(i); // calls f<int&>(int&) 
int n2 = f(0); // calls f<int>(int&&) 
int n3 = g(i); // error: would call g<int>(const int&&) 

to jest dokładnie to twoja sprawa.

Powiązane problemy