我试图通过(可变)lambda中的副本捕获一个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中定义&#34;类型[...]是相应的捕获实体的类型&#34;,所以我想这将包括cv-specifiers 但这似乎并不直观。
答案 0 :(得分:6)
首先,具有捕获的lambda表达式的类型是类类型(5.1.2 Lambda表达式[expr.prim.lambda]#3)
该类型的operator()
默认为const
,除非在lambda表达式中使用mutable
([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(); };
}
我想混淆源于这样一个事实:lambda声明符中的mutable
涉及const
的{{1}} - 而不是operator()
- {闭包类型的数据成员。与成员函数一样,使用mutable
会更自然,但我想标准委员会希望const
成为默认值。
答案 1 :(得分:1)
这将在C ++ 14下工作,而不是C ++ 11的解决方案。
struct Foo
{
Foo(){}
void Func(){}
};
int main()
{
const Foo foo;
[foo = foo]() mutable { foo.Func(); };
}
但是我真的不明白为什么[foo]
保留const而不保留[foo = foo]
。
答案 2 :(得分:0)
另一种可能的解决方法:
struct Foo
{
Foo(){}
void Func(){}
};
int main()
{
const Foo foo;
{
Foo& fooo= const_cast<Foo&>(foo);
[fooo]() mutable { fooo.Func(); };
}
}
此解决方案存在安全问题(可能通过非const引用意外修改const对象),但避免了额外的复制。