Übergeben von Argumenten an std::async Verweis fehl
Habe ich bemerkt, dass es unmöglich ist zu passieren, eine nicht-const-Referenz als argument an std::async
.
#include <functional>
#include <future>
void foo(int& value) {}
int main() {
int value = 23;
std::async(foo, value);
}
Mein compiler (GCC 4.8.1) gibt den folgenden Fehler für dieses Beispiel:
error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’
Aber wenn ich wickeln Sie den Wert übergeben std::async
im std::reference_wrapper
ist alles OK. Ich gehe davon aus dies ist weil std::async
dauert es Argumente von Wert, aber ich verstehe immer noch nicht den Grund für den Fehler.
- Keine Notwendigkeit zu geben
std::reference_wrapper
. Verwendenstd::ref
. - Ich verwende
std::ref
, aber danke für den Tipp 🙂 - Sie haben zu Graben in den source-code von libstdc++ wenn du daran interessiert bist, den Grund für diesen Fehler ist: gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/... Die Zeilennummern zu sehen sind die Fehler. Viel Glück.
- Bei der Verwendung von libc++ ein ähnlicher Fehler entsteht, d.h., beabsichtigt scheint. Ich konnte nicht finden, dass die Klausel in der standard-Mandatierung dieses Verhalten jedoch. Beachten Sie auch, dass nur mit
std::ref()
löst nicht das problem: es wird ein anderes! Sie müssen nun sicherstellen, dass die Referenz-variable bleibt genug Zeit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist eine bewusste design-Wahl/trade-off.
Ersten, ist es nicht unbedingt möglich, um herauszufinden, ob die functionoid übergeben
async
nimmt seine Argumente per Referenz oder nicht. (Wenn es keine einfache Funktion, sondern eine Funktion, Objekt, könnte es haben einen überladenen Funktionsaufruf-operators, zum Beispiel.) Soasync
kann nicht sagen, "Hey, lassen Sie mich nur überprüfen, was die target-Funktion will, und ich werde das richtige tun."So dass die design-Frage ist, dauert es, alle Argumente als Verweis, wenn möglich (d.h. wenn Sie lvalues), oder tut es immer Kopien machen? Die Anfertigung von Kopien ist die sicher hier die Wahl: eine Kopie kann nicht baumelt, und eine Kopie kann nicht aufweisen race conditions (es sei denn, es ist wirklich komisch). Also, das ist die Wahl, die gemacht wurde: alle Argumente werden kopiert standardmäßig.
Aber dann, der Mechanismus ist so geschrieben, dass es nicht wirklich übergeben Sie dann die Argumente für eine nicht-const lvalue reference-parameter. Das ist eine andere Wahl für die Sicherheit: anders, die Funktion, die Sie erwarten würden, um zu ändern Ihre original-lvalue stattdessen ändert die Kopie, was zu bugs, die sind sehr schwer aufzuspüren.
Aber was, wenn Sie wirklich, wirklich wollen, dass die non-const lvalue reference-parameter? Was, wenn Sie Versprechen, watch out für hängende Referenzen und race conditions? Das ist es, was
std::ref
ist für. Es ist ein explizites opt-in, um die gefährliche Referenz-Semantik. Es ist Ihre Art zu sagen, "ich weiß, was ich hier mache."std::async
(und andere Funktionen, die perfect forwarding) schauen Sie sich die Art der Argumentation, die Sie passieren, um herauszufinden, was zu tun ist. Sie sehen nicht, wie dieses argument wird schließlich verwendet werden. Also, übergeben Sie ein Objekt über eine Referenz, die Sie brauchen, um zu sagenstd::async
ob Sie eine Referenz. Jedoch, einfach die übergabe einer Referenz nicht tun. Verwenden Siestd::ref(value)
übergebenvalue
- by-reference.Das Problem an sich ist nur geringfügig Bezug auf
std::async()
: Wenn Sie das Ergebnis der operationstd::async()
verwendetstd::result_of<...>::type
mit all seinen Argumenten wirdstd::decay<...>::type
'ed. Dies ist vernünftig, weilstd::async()
nimmt beliebige Typen und leitet Sie zum speichern in einem bestimmten Ort. Zu speichern diese Werte sind notwendig für die Funktion Objekt-als auch für die Argumente. Sostd::result_of<...>
verwendet wird, ähnlich zu diesem:... und da
int
kann nicht gebunden werden, um eineint&
(int
ist kein lvalue wurde der Typ wird benötigt, um gebunden werden zuint&
), dies schlägt fehl. Versagen bedeutet in diesem Fall, dassstd::result_of<...>
nicht definieren einer verschachteltentype
.Einer follow-up-Frage könnte sein: Was ist an diesem Typ instanziiert
std::result_of<...>
? Die Idee ist, dass der Funktionsaufruf-syntax, bestehend ausResultType(ArgumentTypes...)
missbraucht: statt der Ergebnis-Typ einer Funktion vom Typ übergeben, undstd::result_of<...>
bestimmt den Typ der Funktion, die aufgerufen wird, wenn die Funktion den Typ mit dem angegebenen Liste von Argumenten aufgerufen wird. Für die Funktion der Zeiger-Typen es ist nicht wirklich so interessant, aber die Funktion Typ kann auch eine function-Objekt, wo die überlastung muss berücksichtigt werden. Also im Grundestd::result_of<...>
wird wie folgt verwendet: