lambda闭包中复制的const对象不可变

z33*_*3ky 10 c++ lambda c++11

我试图通过(可变)lambda中的副本捕获一个const对象.然而,我的编译器抱怨说,捕获的对象是const.

是不是可以将对象复制为非const?

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

int main()
{
    const Foo foo;
    [foo]() mutable { foo.Func(); };
}
Run Code Online (Sandbox Code Playgroud)

用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*’
Run Code Online (Sandbox Code Playgroud)

使用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(); });
Run Code Online (Sandbox Code Playgroud)

标准文档(或者说草案......)在5.1.2.14中定义"类型[...]是相应捕获实体的类型",所以我想这将包括cv-specifiers.
虽然看起来并不直观.

chi*_*ill 6

首先,具有捕获的lambda表达式的类型是类类型(5.1.2 Lambda表达式[expr.prim.lambda]#3)

operator()默认情况下const,该类型具有,除非mutable在lambda表达式中使用([expr.prim.lambda]#5)

接下来,对于作为副本捕获的每个实体,在闭包类型中声明一个未命名的成员.[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(); };
}
Run Code Online (Sandbox Code Playgroud)

我想混淆源于这样一个事实:mutable在lambda声明器中涉及闭包类型的数据成员const的性能operator(),而不是mutable性能.const与成员函数一样,使用它会更自然,但我想标准委员会希望const成为默认值.