2017-01-18 63 views
46
#include <iostream> 

void IsTrue(const bool value) { 
    if (value) { 
    std::cout << "value is True!\n"; 
    } 
} 

int main() 
{ 
    IsTrue([]() { ; /* some lambda */ }); 

    return 0; 
} 

wyjściowa:Dlaczego lambda jest konwertowana na wartość bool, której wartość jest prawdziwa?

value is True! 

Dlaczego lambda ocenić na true na GCC & dzyń? MSVC nie może tego zbudować (nie można przekonwertować lambda na bool).

Czy jest to błąd kompilatora? Albo który akapit normy na to pozwala?

+11

Nie jestem pewien, czy jest to legalne, czy nie, ale wydaje się, że konwertuje lambdę na wskaźnik funkcji, a następnie używa tej wartości (która nie jest pusta) w bool, więc kompiluje. Jeśli dodasz przechwytywanie [nie uda się skompilować] (http://coliru.stacked-crooked.com/a/f28beac0173e86e4). – NathanOliver

+8

MSVC ma [niestandardowe rozszerzenie] (https://adishavit.github.io/2016/magical-captureless-lambdas/), więc wymaga jawnie przeliterować typ wskaźnika funkcji docelowej, w przeciwnym razie konwersja się nie powiedzie. – cpplearner

+0

Zobacz także: [Podawanie lambda jako wskaźnika funkcji] (http://stackoverflow.com/q/28746744/1708801) –

Odpowiedz

44

Standard (§5.1.2) C++ 14 mówi:

Rodzaj zamknięcia dla non-generic lambda wyrażenia bez lambda-wychwytywania ma publicznych o charakterze -Virtual bez wyraźnego konwersji const funkcji do wskaźnika funkcjonować z C wiązanie ++ języków (7,5) mającego te same parametry oraz powrót Wykonania funkcji dla obsługi danego typu Zamknięcie-tych. Wartość zwrócona przez tę funkcję konwersji musi być adresem funkcji, która po wywołaniu ma taki sam efekt, jak wywołanie operatora wywołania funkcji typu zamknięcia.

Ponieważ wskaźnik funkcji jest domyślnie wymienialny na bool, otrzymasz wynik, który pokazałeś. Jest to całkowicie legalne.

MSVC nie skompiluje tego, ponieważ ten operator konwersji jest przeciążony różnymi konwencjami wywołania (__stdcall, __cdecl itd.). Podczas kompilacji dla x64 wszystkie te konwencje wywoływania nie są używane, więc jest tylko jeden operator konwersji i kompiluje on dobrze.