2015-05-06 4 views
8

dieses comment Inspired über Lambdas mit rvalue Referenzparameter direkt an std::async, Binden eines rvalue zu einem Lambda durch std::async Kompilierungen Bindung und führt wie erwartet: (live exampleUnterschied zwischen std :: async und std :: binden, wenn Umwickeln rvalue lambda Referenz

)
auto lambda = [] (std::string&& message) { 
    std::cout << message << std::endl; 
}; 
auto future = std::async(lambda, std::string{"hello world"}); 
future.get(); 

std::bind Verwendung, löst jedoch einen Compiler-Fehler: (live example)

auto lambda = [] (std::string&& message) { 
    std::cout << message << std::endl; 
}; 
auto bound = std::bind(lambda, std::string{"hello world"}); // Compiler error 
bound(); 

Dies liegt daran, std::bind behält message als Lvalue, so dass, wenn es an das Lambda übergeben wird, das Argument nicht mehr mit dem Parameter übereinstimmt.

Ich habe read dass std::async intern std::bind verwendet, so wie es mit rvalue Referenzparameter nicht weg, wenn std::bind nicht der Fall ist? Gibt es einen bestimmten Teil des Standards, der dieses Verhalten erfordert oder vom Compiler abhängig ist?

Antwort

4

I've read that std::async internally uses std::bind , so how does it get away with rvalue reference parameters when std::bind does not?

Es verwendet bind intern nicht. (Oder besser gesagt, es könnte nicht ohne einige epische Verrenkungen wie die in @Praetorian's answer in that question, und es ist viel einfacher, etwas separat zu schreiben).

Es ist in der Regel implementiert eine etwas bind -ähnlichen Maschinen verwenden, aber es ist viel einfacher, weil es nicht alle möglichen seltsamen Dinge zu behandeln hat bind Griffe (verschachtelt bind s, Platzhalter, zusätzliche Argumente fallen, etc.)

Is there a particular part of the standard that requires this behavior or is this dependent on the compiler?

Es ist durch den Standard erforderlich. Die Spezifikation von bind ist lächerlich dicht, erfordert aber, dass schrankenlose Argumente als lvalues ​​([func.bind.bind]/p10, bullet 4) übergeben werden.

async wird zum Aufruf INVOKE (DECAY_COPY (std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) angegeben, und DECAY_COPY gibt immer einen Rvalue zurück.

Verwandte Themen