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

Может ли указатель на участников обходить уровень доступа члена?

В нашей печально известной лампочке есть интересная статья о как обойти проверку доступа.

Это полностью подтверждается этим простым кодом:

#include <iostream>

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

Что компилируется и запускается (вывод 42) с gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 (см. комментарий пользователя1131467) и компилируется с Clang 3.0 и Comeau C/С++ 4.3.10.1 в строгом режиме С++ 03 и MSVC 2005.

Меня спросил Luchian на этом ответе, в котором я использовал его, чтобы оправдать, что он был действительно законным. Я согласен с Luchian, что это странно, однако Clang и Comeau являются близкими соперниками для большинства доступных "стандартных" компиляторов (гораздо больше, чем MSVC по умолчанию)...

И я не мог найти ничего в проектах Стандартов, которые у меня есть (n3337 - последняя версия, на которую я получил свои руки).

Итак... может ли кто-нибудь на самом деле оправдать, что он юридический или нет?

4b9b3361

Ответ 1

Да, это правовая. Соответствующий текст приведен в §14.7.2/12, говоря о явной реализации шаблона:

12 Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров. [Примечание. В частности, аргументы шаблона и имена, используемые в деклараторе функций (включая типы параметров, типы возвращаемых данных и спецификации исключений), могут быть частными типами или объектами, которые обычно не будут доступны, а шаблон может быть шаблоном-членом или функцией-членом который обычно не был бы доступны. - конечная нота]

Эмпасис мой.

Ответ 2

Код явно незаконный (и требуется диагностика времени компиляции). В строке:

template struct Rob<A_f, &A::a>;

выражение A::a обращается к частному члену A.

В стандарте очень четко сказано: "применяется контроль доступа равномерно для всех имен, от которых связаны имена декларации или выражения "(§11/4, добавлено выделение). Поскольку A является частным именем в A, любая ссылка на него вне A является незаконной.