Uczę się std::forward
. Napisałem krótki program do sprawdzenia, co się stanie, jeśli nie nazywamy std::forward
przed przekazaniem argumenty do innego wywołania funkcji:Dlaczego łańcuchy C++ nie potrzebują std :: forward, aby wywołać pożądaną funkcję?
#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;
}
Tutaj starałem się przekazać lwartość i rvalue z test_forward_wrapper()
do test_forward_inner()
. Uruchomienie tego programu daje wyjście:
& example
& example
& hello
&& hello
Dla std::string
s, pożądana funkcja wewnętrzna został powołany, ale dla własnej klasy tylko wersja lwartość nazwano. Dopiero po wywołaniu std::forward
przed przekazaniem argumentów do funkcji wewnętrznej można wywołać wersję rvalue.
Co robi różnicę tutaj? Jak wiem, zgodnie z referencyjnymi regułami zwijania, gdy opakowanie było wywoływane z Example()
, wartość r, T
byłaby wydedukowana jako Example
i arg
miałaby typ Example &&
, dlatego powinna zostać wywołana wersja rubliczna funkcji wewnętrznej.
W przypadku innych sytuacji, takich jak tutaj: std::string
, została wywołana prawidłowa wersja funkcji wewnętrznej, czy możemy usunąć tutaj kod std::forward
? Jeśli nie, to co (może coś złego) się stanie?
Ważne jest to, że owijka jest matrycy (a więc nie pojawia się w tym przymus połączenia), przy czym funkcja wewnętrzna nie tylko przyjmowania 'std :: string', co oznacza przemianę' string' zachodzi następnie (podając referencję wartości r do funkcji wewnętrznej), nie ma potrzeby przekazywania. – ShadowRanger
'" cześć "' nie jest 'const char *', jest to 'const char [6]', które może zepsuć się do 'const char *'. . –
^(i nie gnije w tej sytuacji) –