200

constラムダ式で参照によってキャプチャすることは可能ですか?

たとえば、以下にマークされた割り当てを失敗させたい:

#include <algorithm>
#include <string>

using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";

    for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
      {
        best_string = s; // this should fail
      }
    );
return 0;
}

更新:これは古い質問であるため、これを支援する機能が C++14 にある場合は更新することをお勧めします。C++14 の拡張機能により、const 参照によって非 const オブジェクトをキャプチャできますか? ( 2015年8月)

4

8 に答える 8

164

/を使用する場合:static_castconst_cast

[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
    best_string = s; // fails
};

デモ


で次を使用std::as_const

[&best_string = std::as_const(best_string)](const string& s)
{
    best_string = s; // fails
};

デモ 2

于 2015-09-07T13:56:35.983 に答える
136

constn3092 の時点で、キャプチャの文法にはありません:

capture:
  identifier
  & identifier
  this

テキストは、コピーによるキャプチャと参照によるキャプチャについてのみ言及しており、あらゆる種類の const-ness については言及していません。

私には見落としのように感じますが、私は標準化プロセスにあまり厳密に従っていません。

于 2010-09-22T19:40:16.753 に答える
16

キャプチャ部分は を指定すべきではないと思います。constキャプチャ手段としては、外側のスコープ変数にアクセスする方法だけが必要です。

指定子は、外側のスコープで指定することをお勧めします。

const string better_string = "XXX";
[&better_string](string s) {
    better_string = s;    // error: read-only area.
}

ラムダ関数はconst(スコープ内の値を変更できない)であるため、変数を値でキャプチャすると、変数は変更できませんが、参照はラムダスコープ内にありません。

于 2014-01-04T03:20:28.390 に答える
9

変数をファンクターのパラメーターとして使用していない場合は、現在の関数のアクセス レベルを使用する必要があると思います。すべきではないと思う場合は、ラムダをこの関数から分離してください。それはその一部ではありません。

とにかく、代わりに別の const 参照を使用することで、同じことを簡単に実現できます。

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";
    const string& string_processed = best_string;

    for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
    {
        string_processed = s;    // this should fail
    }
    );
    return 0;
}

しかし、それはあなたのラムダが現在の関数から分離されなければならず、それを非ラムダにする必要があると仮定するのと同じです。

于 2010-09-22T21:23:14.247 に答える
5

次の 3 つのオプションがあると思います。

  • const 参照を使用せず、コピー キャプチャを使用する
  • 変更可能であるという事実を無視する
  • std::bind を使用して、const 参照を持つバイナリ関数の 1 つの引数をバインドします。

コピーを使用する

コピー キャプチャを使用したラムダの興味深い点は、これらが実際には読み取り専用であるため、希望どおりに動作することです。

int main() {
  int a = 5;
  [a](){ a = 7; }(); // Compiler error!
}

std::bind の使用

std::bind関数のアリティを減らします。ただし、これは関数ポインタを介した間接関数呼び出しにつながる可能性があることに注意してください。

int main() {
  int a = 5;
  std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
于 2013-12-11T20:19:37.583 に答える
0

clang を使用するか、この gcc バグが修正されるまで待ちます: バグ 70385: const 参照の参照によるラムダ キャプチャが失敗する [ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385 ]

于 2016-11-16T16:33:44.807 に答える