2015-05-06 17 views
8

spunto da questo comment merito lambda con parametri di riferimento rvalue legandosi direttamente al std::async, associare un rvalue ad un lambda attraverso std::async compila ed esegue come previsto: (live example)Differenza tra std :: asincrono e std :: bind quando l'involucro rvalue riferimento lambda

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

Utilizzando std::bind, però, innesca un errore di compilazione: (live example)

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

Questo perché std::bind mantiene message come un lvalue, in modo che quando lo passa al lambda, l'argomento non corrisponde più al parametro.

ho read che std::async utilizza internamente std::bind, così come si ottiene via con parametri di riferimento rvalue quando std::bind non lo fa? Esiste una parte particolare dello standard che richiede questo comportamento o dipende dal compilatore?

risposta

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?

Non usa bind internamente. (O meglio, non avrebbe potuto passare attraverso alcune contorsioni epiche come quella di @Praetorian's answer in that question, ed è molto più semplice scrivere qualcosa separatamente).

Di solito è implementato utilizzando un macchinario po bind -come, ma è molto più semplice, perché non ha bisogno di gestire tutti i tipi di cose strane bind maniglie (nidificate bind s, segnaposto, che cadono argomenti extra, ecc)

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

È richiesto dallo standard. La specifica di bind è ridicolmente densa, ma richiede che argomenti normali vengano passati come lvalue ([func.bind.bind]/p10, punto 4).

async è specificato per chiamare INVOKE (DECAY_COPY (std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) e DECAY_COPY restituisce sempre un valore.