考虑以下示例:
#include <cassert>
struct S {
auto func() { return +[](S &s) { s.x++; }; }
int get() { return x; }
private:
int x{0};
};
int main() {
S s;
s.func()(s);
assert(s.get() == 1);
}
它用G ++和clang编译,所以我很想期望标准允许这样做。
但是,lambda没有捕获列表,因为+
强制转换为函数指针,所以它不能拥有它。因此,我预计不允许访问S
的私人数据成员
相反,如果它被定义为静态成员函数,它的行为或多或少。
到目前为止,这么好。如果我之前知道它,我会经常使用这个技巧来避免编写冗余代码。
我现在想知道的是标准中的位置(工作草案很好)这是定义的,因为我无法找到章节,子弹或其他任何规则它。
是否对lambda有任何限制,或者它完全,就像它被定义为静态成员函数一样?
答案 0 :(得分:15)
对于成员函数内的lambda表达式,根据§8.4.5.1/2 Closure types [expr.prim.lambda.closure]:
闭包类型在包含相应lambda表达式的最小块作用域,类作用域或命名空间作用域中声明。
这意味着lambda闭包类型将在成员函数内声明,即本地类。根据{{3}}:
(强调我的)
类的成员还可以访问该类有权访问的所有名称。 成员的本地类 函数可以访问成员函数本身可以访问的相同名称。
这意味着对于lambda表达式本身,它可以访问private
的{{1}}成员,与成员函数S
相同。
§14/2 Member access control [class.access]:
(强调我的)
非泛型lambda表达式的闭包类型,没有lambda-capture,其约束(如果有的话)满足了指向函数的转换函数,C ++语言链接具有与闭包类型相同的参数和返回类型#39; s函数调用操作符。 ... 此转换函数返回的值是函数F的地址,在调用时,它与调用闭包类型的函数调用运算符具有相同的效果。
这意味着当调用转换的函数指针时,适用相同的规则。
答案 1 :(得分:6)
但是,lambda没有捕获列表,因为
+
强制转换为函数指针,所以它不能拥有它。
+
不会强制转换为函数指针,但会将转换运算符添加到指向函数的指针,以供您用作选项。 Lambda仍然是lambda,具有授予它的所有访问权限,即它可以访问成员函数本身可以访问的相同名称。