Як "int main () {(([] () {}) ());}" дійсний C ++?


271

Нещодавно я натрапив на наступний езотеричний фрагмент коду.

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

Переформатуйте його наступним чином, щоб зробити його більш зрозумілим:

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

Але я не можу опустити голову як (([](){})()) діє код.

  • Це не схоже на синтаксис вказівника функції.
  • Це не може бути трюком перевантаження оператора. Код складається так, як є.

Google не дуже допомагав у цьому пошуку всіх символів. Але вона компілюється у Visual Studio 2010 і нічого не видає. Не було помилок і жодних попереджень. Так виглядає дійсний код.

Я ніколи не бачив якого - або дійсного коду , який так дивно за межами Javascript і C покажчиків функцій .

Чи може хтось пояснити, наскільки це дійсно C ++?


94
Гей! Це моє. "Don't sweat it. We have int main(){(([](){})());} which is valid C++" (9 листопада в чаті)
вересня 1212

31
це закриття лямбда c ++ 11

7
@Mysticial - Цей код містифікує вас, оскільки він марний. Якщо ця лямбда зробила б щось, ви б визнали, що він має синтаксис, подібний до функціональних покажчиків (з якими він тісно пов'язаний).
SChepurin

14
@Mysticial - "6 років C ++" - лямбдаші були щойно додані в C ++ 11, тому ніхто не мав досвіду роботи з ними ще рік тому.
Піт Бекер

50
URL-адреса тут дуже кумедна: "how-is-int-main-valid-c"
tckmn

Відповіді:


283

Код по суті називає порожньою лямбда.

Почнемо з початку: [](){}це порожній лямбда-вираз .

Тоді, в C і C ++, ви можете обернути вираження в круглих дужках , і вони ведуть себе точно так само , як якби написано без них, так це те, що перша пара дужок навколо лямбда робить. Зараз ми в([](){}) .

Тоді, () після першого обгортання парен називає (порожню) лямбда. Зараз ми в([](){})()

Весь вираз знову загортається в парену і ми отримуємо (([](){})()) .

Нарешті, ;закінчується твердженням. Ми приїжджаємо (([](){})());.


† Принаймні в C ++ є деякі кутові випадки, як, наприклад T a_var; , різниця між decltype(a_var)іdecltype((a_var)) .


7
Пропустив кинджал.
Р. Мартіньо Фернандес

33
@ R.MartinhoFernandes: Він все ще в когось застряг, тому мені довелося піти і отримати його.
Xeo

1
Я збирався висловитись за те, щоб правильно згадати випадок, коли додавання () навколо виразу змінює семантику. Але потім я згадав, що це питання ніякого відношення не має. Приємна відповідь
вересня 1212

2
В дужках також змінюється значення програми у випадку найбільш неприємного розбору розбору: B foo(A())foo - це функція (беручи вказівник на функцію лише в якості параметра і повертаючи B), тоді як у B foo((A()))foo - об'єкт B, побудований із посиланням на конструктор, що приймає a Об'єкт (екземпляр якого в даному випадку є анонімним тимчасовим).
Оголошення N

1
@AdN: Це вже не вираз, а декларація.
Xeo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.