In che modo "int main () {(([] () {}) ());}" è valido C ++?


271

Di recente mi sono imbattuto nel seguente pezzo di codice esoterico.

int main(){(([](){})());}

Riformattalo come segue per renderlo più leggibile:

int main(){
    (([](){})());   //  Um... what?!?!
}

Ma non riesco a capire come (([](){})())sia valido il codice.

  • Non sembra la sintassi del puntatore a funzione.
  • Non può essere un trucco da sovraccarico per l'operatore. Il codice viene compilato così com'è.

Google non ha aiutato molto con questa ricerca con tutti i simboli. Ma si compila in Visual Studio 2010 e non genera nulla. Non ci sono stati errori e nessun avviso. Quindi sembra un codice valido.

Non ho mai visto alcun codice valido che è così bizzarra al di fuori di Javascript e C puntatori a funzione .

Qualcuno può spiegare come questo è C ++ valido?



31
è una chiusura lambda c ++ 11

7
@Mysticial - Questo codice ti confonde perché è inutile. Se questo lambda dovesse fare qualcosa, lo riconosceresti con una sintassi simile ai puntatori di funzione (con i quali è strettamente correlato).
SChepurin,

14
@Mysticial - "6 anni di C ++" - i lambda sono stati appena aggiunti in C ++ 11, quindi nessuno ha esperienza con loro prima di circa un anno fa.
Pete Becker,

50
L'URL qui è abbastanza divertente: "how-is-int-main-valid-c"
tckmn

Risposte:


283

Il codice essenzialmente chiama un lambda vuoto.

Partiamo dall'inizio: [](){}è un'espressione lambda vuota .

Quindi, in C e C ++, puoi racchiudere le espressioni in parentesi e si comportano esattamente come come se fossero scritte senza di loro, quindi è quello che fa la prima coppia di parentesi attorno alla lambda. Ora siamo a ([](){}).

Quindi, ()dopo il primo avvolgimento, parentesi chiama il (vuoto) lambda. Ora siamo a([](){})()

L'intera espressione è di nuovo racchiusa tra parentesi e otteniamo (([](){})()).

Alla fine, ;termina la dichiarazione. Arriviamo a (([](){})());.


† Ci sono alcuni casi angolari almeno in C ++, come nel T a_var; caso di una differenza tra decltype(a_var)edecltype((a_var)) .


7
Mancava un pugnale.
R. Martinho Fernandes,

33
@ R.MartinhoFernandes: era ancora bloccato in qualcuno, quindi ho dovuto andare a recuperarlo.
Xeo,

1
Avrei votato per aver citato correttamente il caso in cui l'aggiunta di () attorno a un'espressione altera la semantica. Ma poi ho ricordato che non ha alcuna relazione con la domanda, davvero. Bella risposta
visto il

2
Le parentesi stanno anche cambiando il significato di un programma nel caso della più fastidiosa disambiguazione dell'analisi: B foo(A())foo è una funzione (prendere un puntatore per funzionare come unico parametro e restituire una B) mentre in B foo((A()))foo è un oggetto B costruito invocando un costruttore che prende a Un oggetto (quale istanza è un temporaneo anonimo in questo caso).
Annuncio N

1
@AdN: non è più un'espressione, ma una dichiarazione.
Xeo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.