「int main(){(([](){})());}」は有効なC ++ですか?


271

最近、次の難解なコードに出くわしました。

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

次のように再フォーマットして、読みやすくします。

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

しかし、私(([](){})())は有効なコードがどうあるかについて頭をつかむことができません。

  • 関数ポインタ構文のようには見えません。
  • オペレーターのオーバーロードのトリックにはなりません。コードはそのままコンパイルされます。

グーグルは、この全記号検索ではあまり役に立たなかった。ただし、Visual Studio 2010でコンパイルされ、何も出力されません。エラーも警告もありませんでした。したがって、有効なコードのように見えます。

私は、JavaScriptC関数ポインター以外ではとても奇妙な有効なコードを見たことがありません。

これが有効なC ++であると誰かが説明できますか?


94
おい!私の物です。"Don't sweat it. We have int main(){(([](){})());} which is valid C++"(11月9日のチャット)
sehe

31
それは、C ++ 11のラムダ閉鎖だ

7
@Mysticial-役に立たないため、このコードはあなたを不可解にします。このラムダが何かを実行する場合、関数ポインタ(これは密接に関連している)に類似した構文を持っていることがわかります。
シェプリン

14
@Mysticial-「6年間のC ++」-ラムダはC ++ 11で追加されたばかりなので、1年ほど前に誰もそれらの経験はありません。
ピートベッカー

50
ここのURLはかなりおもしろい: "how-is-int-main-valid-c"
tckmn

回答:


283

コードは基本的に空のラムダを呼び出します。

最初から始めましょう:[](){}空のラムダ式です。

次に、CおよびC ++では、式を括弧で囲むことができ、それらは式なしで記述された場合とまったく同じように動作します、それがラムダの周りの括弧の最初のペアが行うことです。現在にい([](){})ます。

次に、()最初のラッピング後、括弧が(空の)ラムダを呼び出します。私たちは今です([](){})()

式全体が再び括弧で囲まれ、取得され(([](){})())ます。

最後に;、ステートメントを終了します。到着し(([](){})());ます。


† とには違いがあるように、少なくともC ++にはいくつかのコーナーケースT a_var; decltype(a_var)ありdecltype((a_var))ます。



33
@ R.MartinhoFernandes:それはまだ誰かに引っかかっていたので、私はそれを取りに行かなければならなかった。
Xeo

1
式の周りに()を追加することでセマンティクスが変わる場合について正しく言及したことに対して賛成票を投じていました。でも、それが問題とは関係ないことを覚えていました。いい答え
sehe

2
かっこは、最も厄介な解析の曖昧性解消の場合にプログラムの意味も変更します。foo B foo(A())は関数(関数へのポインターをパラメーターとしてのみ受け取り、Bを返す)ですが、B foo((A()))fooはコンストラクターを呼び出すように構築されたBオブジェクトですaオブジェクト(この場合、インスタンスは匿名の一時的です)。
Ad N

1
@AdN:もはや式ではなく、宣言です。
Xeo 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.