Когда функция lambda объявлена внутри функции F
, которая является другом класса C
, имеет ли лямбда-функция доступ к C
частным членам? В частности, разрешает ли это стандарт?
С++ лямбда-дружба
Ответ 1
С++ 11 § [expr.prim.lambda] 5.1.2/3:
Тип лямбда-выражения (который также является типом объекта замыкания) - это уникальный, неназванный тип неединичного класса, называемый типом замыкания, свойства которого описаны ниже. Этот тип класса не является совокупностью (8.5.1). Тип закрытия объявляется в наименьшей области блока, области видимости класса или области пространства имен, которая содержит соответствующее лямбда-выражение....
Так как тип замыкания объявлен в функции друга, он будет иметь тот же доступ к § [class.local] 9.8/1:
Класс может быть объявлен в определении функции; такой класс называется локальным классом. Имя локального класса является локальным для его охватывающей области. Локальный класс входит в объем охватывающей области и имеет тот же доступ к именам за пределами функции, что и закрывающая функция....
Ответ 2
Вложенный класс автоматически получает доступ ко всем членам, к которым имеет доступ "владелец". Вам не нужны лямбда, чтобы это увидеть:
class A {
friend struct B;
friend void g();
static void f() { }
};
struct B {
struct C {
static void f() { A::f(); }
};
static void f() { C::f(); }
};
void g() {
struct D {
static void f() { A::f(); }
};
D::f();
}
Несмотря на то, что они явно не указаны в качестве друзей, C::f
и D::f
могут вызывать private A::f
без каких-либо жалоб от компилятора.
Lambdas реализованы с использованием локальных классов, генерируемых компилятором (это не просто деталь реализации, что требуется стандарту), поэтому применяются те же правила, что и для других локальных классов.
Правило, что локальные классы могут обращаться к тем же членам, указано в стандарте в 9.8:
Локальный класс находится в области охватывающей области и имеет тот же доступ к именам вне функции, что и закрывающая функция.