W +wyrażeniu +[](){}jest +operatorem jednoargumentowym . W [expr.unary.op] / 7 jest zdefiniowany w następujący sposób:
Operand +operatora jednoargumentowego powinien mieć typ arytmetyczny, wyliczeniowy bez zakresu lub typ wskaźnika, a wynikiem jest wartość argumentu.
Lambda nie jest typu arytmetycznego itp., Ale można ją przekonwertować:
[wyr.prim.lambda] / 3
Typ wyrażenia lambda [...] jest unikalnym, nienazwanym typem klasy nieunijnej - zwanym typem zamknięcia - którego właściwości opisano poniżej.
[wyr.prim.lambda] / 6
Typ zamknięcia do lambda ekspresji bez lambda chwytania ma publicNieskarbowych virtualNieskarbowych explicit constfunkcję konwersji do wskaźnika do funkcji o tych samych typów parametrów i powrotnym dla obsługi funkcji danego typu Zamknięcie-tych. Wartość zwracana przez tę funkcję konwersji będzie adresem funkcji, która po wywołaniu ma taki sam skutek, jak wywołanie operatora wywołania funkcji typu zamknięcia.
Dlatego jednoargumentowa +wymusza konwersję do typu wskaźnika funkcji, który jest dla tej lambdy void (*)(). Dlatego typ wyrażenia +[](){}to ten typ wskaźnika funkcji void (*)().
Drugie przeciążenie void foo(void (*f)())staje się dokładnym dopasowaniem w rankingu rozpoznawania przeciążenia i w związku z tym jest wybierane jednoznacznie (ponieważ pierwsze przeciążenie NIE jest dokładnym dopasowaniem).
Lambda [](){}można przekonwertować na std::function<void()>za pomocą niejawnego edytora szablonu programu std::function, który przyjmuje dowolny typ, który spełnia wymagania Callablei CopyConstructible.
Lambda można również przekonwertować na void (*)()funkcję konwersji typu zamknięcia (patrz wyżej).
Obie są sekwencjami konwersji zdefiniowanymi przez użytkownika i mają tę samą rangę. Dlatego rozpoznawanie przeciążenia w pierwszym przykładzie zawodzi z powodu niejednoznaczności.
Zdaniem Cassio Neri, popartego argumentem Daniela Krüglera, ta jednoargumentowa +sztuczka powinna być określonym zachowaniem, tj. Można na nim polegać (patrz dyskusja w komentarzach).
Mimo to polecam użycie jawnego rzutowania na typ wskaźnika funkcji, jeśli chcesz uniknąć niejednoznaczności: nie musisz pytać SO, co się dzieje i dlaczego działa;)
std::bindzstd::functionobiektem, który można wywołać podobnie do funkcji lwartość.