1. ホーム
  2. c++

[解決済み] 構造化バインディングで宣言された変数でラムダの暗黙のキャプチャに失敗する

2023-01-26 04:43:51

質問

以下のコードで、コンパイルエラーが発生します。 C2065 'a': undeclared identifier (と表示されます(visual studio 2017使用)。

[] {
    auto [a, b] = [] {return std::make_tuple(1, 2); }();
    auto r = [&] {return a; }(); //error C2065
}();

しかし、以下のコードはコンパイルされます。

[] {
    int a, b;
    std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
    auto r = [&] {return a; }();
}();

この2つのサンプルは同じものだと思っていました。コンパイラのバグでしょうか、それとも何か見逃しているのでしょうか?

どのように解決するのですか?

コア問題2313 は、構造化されたバインディングが決して変数名ではなく、決して捕捉できないように標準を変更しました。

P0588R1 のラムダ キャプチャの表現の再定式化により、この禁止が明示されました。

<ブロッククオート

ラムダ式[...]が構造化されたバインディングを(明示的または暗黙的に)捕捉している場合,プログラムは不正確である。 または暗黙のうちに)、プログラムは不正な形式です。

この文言は、委員会がそのようなキャプチャがどのように機能すべきかを正確に把握する間のプレースホルダであると思われることに注意してください。

歴史的な理由により、以前の回答は保存されています。


これは技術的にはコンパイルできるはずですが、ここに標準のバグがあります。

標準では、ラムダは変数だけを捕らえることができると言っています。そして、タプルのようでない構造化バインディング宣言は変数を導入しないと言っています。それは名前を導入しますが、それらの名前は変数の名前ではありません。

一方、タプルライクな構造化バインディング宣言は。 を行います。 は変数を導入します。 abauto [a, b] = std::make_tuple(1, 2); は実際の 参照型変数です。ですから、ラムダで捕捉することができます。

明らかにこれは正気の状態ではなく、委員会はこれを知っているので、修正が来るはずです(ただし、構造化バインディングをどのようにキャプチャするかについては、正確にいくつかの不一致があるようです)。