[解決済み】 正のラムダ:'+[]{}' - これは何の妖術か?[重複している]
質問
Stack Overflowの質問で C++11ではラムダの再定義ができない、なぜ? という、コンパイルできない小さなプログラムが渡されました。
int main() {
auto test = []{};
test = []{};
}
質問にも答えていただき、すべて順調のようでした。その後 ヨハネス・シャウプ を作成し 興味深い見解です。 :
をつけると
+
の前に置くと、魔法のように動き出します。
そこで気になるのは、なぜ次のようにするとうまくいくのか、ということです。
int main() {
auto test = +[]{}; // Note the unary operator + before the lambda
test = []{};
}
の両方でも問題なくコンパイルできます。 GCC 4.7+と Clang 3.2+. コードの規格は適合していますか?
解決方法は?
はい、コードは標準に準拠しています。その
+
は、ラムダを単なる古い関数ポインタに変換するきっかけとなります。
どうなるかというと、こうなります。
コンパイラは、最初のラムダ(
[]{}
) に従って、クロージャ・オブジェクトを生成します。このラムダは
非捕獲
lambdaを使用すると、次のようになります。
5.1.2 ラムダ式 [expr.prim.lambda] の場合
6 のクロージャーのタイプは ラムダ式 がなく ラムダキャプチャ は,クロージャ型の関数呼び出し演算子と同じパラメータと戻り値の型を持つ関数へのポインタへの,パブリックな非仮想的な非明示的 const 変換関数を持っている。この変換関数が返す値は、呼び出されたときにクロージャ型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければならない。
これは重要なことで、単項演算子
+
には組み込みのオーバーロードのセットがあり、特にこのオーバーロードは重要です。
13.6 組み込み演算子[over.built]について
8 各タイプについて
T
という形の演算子関数の候補が存在する。
T* operator+(T*);
そして、これによって、何が起こるかは非常に明確です。演算子
+
がクロージャオブジェクトに適用されると、オーバーロードされた組み込みの候補のセットは、変換からANYポインタを含み、クロージャタイプは、ラムダの関数ポインタへの変換というちょうど1つの候補を含んでいます。
の型は
test
で
auto test = +[]{};
は次のように推論されます。
void(*)()
. 2行目は簡単です。2番目のラムダ/クロージャオブジェクトに対して、関数ポインタへの代入が1行目と同じ変換を引き起こします。たとえ2番目のラムダが異なるクロージャの型を持っていても、結果の関数ポインタはもちろん互換性があり、代入することができます。
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】C++11のラムダ式って何?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】識別子 "string "は未定義?
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】浮動小数点数の乱数生成