Подтвердить что ты не робот

С++ лямбда-дружба

Когда функция lambda объявлена ​​внутри функции F, которая является другом класса C, имеет ли лямбда-функция доступ к C частным членам? В частности, разрешает ли это стандарт?

4b9b3361

Ответ 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:

Локальный класс находится в области охватывающей области и имеет тот же доступ к именам вне функции, что и закрывающая функция.