11

(変更可能な) ラムダでコピーを介して const オブジェクトをキャプチャしようとしています。ただし、私のコンパイラは、キャプチャされたオブジェクトが const であると不平を言っています。

オブジェクトを非 const としてコピーすることはできないのでしょうか?

struct Foo
{
    Foo(){}
    void Func(){}
};

int main()
{
    const Foo foo;
    [foo]() mutable { foo.Func(); };
}

g++ 4.7.2 でコンパイル:

testcase.cpp: In lambda function:
testcase.cpp:10:29: error: no matching function for call to ‘Foo::Func() const’
testcase.cpp:10:29: note: candidate is:
testcase.cpp:4:7: note: void Foo::Func() <near match>
testcase.cpp:4:7: note:   no known conversion for implicit ‘this’ parameter from ‘const Foo*’ to ‘Foo*’

clang++ 3.1 でコンパイル:

testcase.cpp:10:20: error: member function 'Func' not viable: 'this' argument has type 'const Foo', but function is not marked const
    std::async([foo]() mutable { foo.Func(); });

標準ドキュメント(またはドラフト...)は、5.1.2.14で「タイプ[...]は対応するキャプチャされたエンティティのタイプである」と定義しているため、cv-specifiersが含まれると思います。
ただし、直感的ではないようです。

4

3 に答える 3

7

まず、capture を持つラムダ式の型はクラス型です (5.1.2 ラムダ式 [expr.prim.lambda] #3)。

がラムダ式で使用されていない限り、その型にはoperator()デフォルトで があります([expr.prim.lambda] #5)constmutable

次に、コピーとしてキャプチャされたエンティティごとに、名前のないメンバーがクロージャー型で宣言されます。[expr.prim.lambda] #14]

(ほぼ) キャプチャ型と同等のものを明示的に構築すると、クラス、const 修飾された型、および const 修飾されたメンバー関数の通常のセマンティクスにすべてが自然に従います。

例:

struct S
{
  void f();
  void fc() const;
};

void g()
{
  S s0;

  // [s0] ()  { s0.f(); }; // error, operator() is const
  [s0] () { s0.fc(); };    // OK, operator() is const, S::fc is const

  [s0] () mutable { s0.f(); };
  [s0] () mutable { s0.fc(); };

  const S s1;

  // [s1] ()  { s1.f(); }; // error, s1 is const, no matter if operator() is const
  [s1] ()  { s1.fc(); };

  // [s1] () mutable { s1.f(); }; // error, s1 is const, no matter if operator() is const
  [s1] () mutable { s1.fc(); };
}

mutable混乱は、ラムダ宣言子では、クロージャー型のデータ メンバーの -ilityではなく、のconst-ness に関係しているという事実から生じていると思います。メンバー関数と同様に を使用する方がより自然ですが、標準化委員会はデフォルトにしたかったと思います。operator()mutableconstconst

于 2012-12-04T10:32:28.550 に答える
1

これは C++11 のソリューションではなく、C++14 で動作します。

struct Foo
{
    Foo(){}
    void Func(){}
};

int main()
{
    const Foo foo;
    [foo = foo]() mutable { foo.Func(); };
}

[foo]しかし、なぜconst を保持しているのに保持していないのか、私にはよくわかり[foo = foo]ません。

于 2019-02-22T09:08:33.157 に答える
0

別の可能な回避策:

  struct Foo
  {
      Foo(){}
      void Func(){}
  };

  int main()
  {
      const Foo foo;
      {
          Foo& fooo= const_cast<Foo&>(foo);
          [fooo]() mutable { fooo.Func(); };
      }
  }

このソリューションには安全上の問題があります (非 const 参照による const オブジェクトの偶発的な変更が可能です) が、追加のコピーは回避されます。

于 2012-12-04T13:00:19.930 に答える