Ich lerne std::forward
. Ich schrieb ein kleines Programm zu testen, was passieren würde, wenn wir nicht std::forward
nennen, bevor die Argumente an einem anderen Funktion Anrufweiterschaltung:Warum C++ - Zeichenfolgen brauchen nicht std :: forward, um die gewünschte Funktion aufzurufen?
#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;
}
Hier habe ich versucht, einen L-Wert und einen R-Wert test_forward_wrapper()
-test_forward_inner()
zu übermitteln. Das Ausführen dieses Programms gibt die Ausgabe:
& example
& example
& hello
&& hello
Für std::string
s wurde die gewünschte innere Funktion genannt, aber für meine eigene Klasse wurde nur die L-Wert-Version genannt. Nur wenn ich rufe, bevor die Argumente an die innere Funktion übergeben werden, kann die rvalue-Version aufgerufen werden.
Was macht hier den Unterschied? Wie ich weiß, würde gemäß den Regeln zum Kollabieren von Referenzen, wenn der Wrapper mit Example()
aufgerufen wurde, ein rvalue, T
als Example
abgeleitet werden und arg
würde den Typ Example &&
haben, daher sollte die rvalue-Version der inneren Funktion aufgerufen werden.
Und für andere Situationen wie der std::string
Fall hier, wurde die richtige Version der inneren Funktion aufgerufen, dann können wir die std::forward
hier entfernen? Wenn nicht, was (vielleicht etwas Schlechtes) würde passieren?
Der wichtige Teil ist, dass die Wrapper-templated ist (so dass kein Zwang in diesem Anruf auftritt), während die innere Funktion nicht der Fall ist, nur 'std :: string' zu akzeptieren, die die Umwandlung zu' string' bedeutet auftritt dann (Bereitstellung eines r-Wert Verweises auf die innere Funktion), keine Weiterleitung beteiligt. – ShadowRanger
'" Hallo "' ist kein 'const char *', es ist ein 'const char [6]', das in ein 'const char *' zerfallen kann. . –
^(und zerfällt in dieser Situation nicht) –