按值可变的 lambda 捕获不适用于 const &?
lambda capture by value mutable doesn't work with const &?
请考虑以下事项:
void test( const int &value )
{
auto testConstRefMutableCopy = [value] () mutable {
value = 2; // compile error: Cannot assign to a variable captured by copy in a non-mutable lambda
};
int valueCopy = value;
auto testCopyMutableCopy = [valueCopy] () mutable {
valueCopy = 2; // compiles OK
};
}
当我将 lambda 声明为可变并按值捕获value
时,为什么第一个版本是编译错误(我认为这是它的副本(?
使用 clang (x86_64-apple-darwin14.3.0( 和 Visual C++ (vc120( 进行测试,这是错误消息的来源。
[C++11: 5.1.2/14]:
如果实体是隐式捕获的并且捕获默认值=
,或者如果使用不包含&
的捕获显式捕获实体,则通过复制捕获实体。对于 copy 捕获的每个实体,将在闭包类型中声明一个未命名的非静态数据成员。未指定这些成员的声明顺序。如果实体不是对对象的引用,则此类数据成员的类型是相应捕获实体的类型,否则为引用的类型。[..]
lambda 中的value
类型是 const int
,因为它是通过从const int&
复制捕获的。
因此,即使 lambda 的调用运算符函数不是const
(您将 lambda 标记为mutable
(,实际的隐式成员value
是 const int
类型并且不能改变。
坦率地说,这似乎很荒谬;我希望这条规则说引用的类型会失去const
,因为它是一个副本。lambda 本身上是否存在 mutable
关键字(因此,生成的调用运算符函数上是否存在 const
关键字(应该是此处唯一的访问控制。
在 C++14 中,您可以通过捕获为 [value=value]
来解决此问题,它使用与 auto
相同的规则,从而删除const
。C++很棒,不是吗?
mutable
允许 lambda 修改由 copy 捕获的非常量参数的副本,但不允许const
参数。
所以这段代码有效(并输出inside 2 outside 1
(:
int a = 1;
[a]() mutable {
a = 2; // compiles OK
cout << "inside " << a << "n";
}();
cout << " outside " << a << "n";
但是如果我们省略mutable
,或者做一个const int
,编译器会给出一个错误。
在我们的例子中,第一个 lambda 给出了一个错误,因为value
const
:
void test( const int &value )
如果我们做copyValue
const
:
const int valueCopy = value;
然后第二个 lambda 将发生相同的错误。
- OpenGL - 在 NDC 中计算位置适用于着色器,但不适用于'regular'程序
- 使用模板参数重载C++方法:如何使其适用于模板的子类?
- 如何修复我的最大公约数代码?它适用于除零和零以外的所有数字
- 选择排序C++(已修改)并非适用于所有情况
- 无法让"std::enable_if"适用于无作用域枚举
- 请找出我的代码中的错误,它在提交得到错误答案的同时仍然适用于我的所有测试用例
- 确定夏令时是否适用于特定日期
- 是否有一种 STL 算法可以最后找到,但它也适用于指针?
- 十进制到二进制的实现不能完全适用于我大学的检查器。问题或提示可能是什么
- 使用程序集嵌入数据时"Undefined reference"错误,使用适用于窗口的 mingw-w64 编译(COFF 而不是 ELF)
- 为什么 std::vector 适用于类定义中的不完整类型?
- 为什么哈希<常量字符*>适用于字符串而不是字符串变量?
- Lambda适用于最新的Visual Studio,但在其他地方不起作用
- 我该如何文档文档以使文档适用于类成员而不是匿名类型
- 计算 c# 中二进制文件符号的频率不起作用,但适用于等效的 c++ 代码
- 为什么 fstream.open(文件名) 适用于文字而不是生成的字符串?
- 模板重载和 SFINAE 仅适用于函数而不是类
- 为什么链接器不抱怨多个函数定义(仅适用于模板化函数)
- 我可以使用' == '来比较两个向量吗?我试过了,似乎工作正常。但我不知道它是否适用于更复杂的情况
- 延长临时的生命周期,适用于块范围的聚合,但不是通过"新";为什么?