Czy wskaźnik do członków może omijać poziom dostępu członka?

Nasz niesławny litb ma ciekawy artykuł na temat jak obejść kontrolę dostępu .

Jest to w pełni zademonstrowane przez ten prosty kod:

#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;
}

Który kompiluje i uruchamia (wyjście 42) z gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 (zobacz komentarz użytkownika 1131467) i kompiluje z Clang 3.0 i Comeau C / C++ 4.3.10.1 w C++03 strict mode i MSVC 2005.

Zostałem zapytany przez Luchiana o tę odpowiedź , w której użyłem jej do uzasadnienia że to było legalne. Zgadzam się z Luchianem, że to dziwne, jednak zarówno Clang, jak i Comeau są bliskimi pretendentami do większości dostępnych" standardowych " kompilatorów (znacznie bardziej niż domyślnie MSVC)...

I nie mogłem znaleźć niczego w projektach standardów, które mam dostępne(n3337 jest ostatnią wersją, którą dostałem w ręce).

Więc... czy ktoś może uzasadnić, że jest to legalne czy nie ?
Author: Community, 2012-03-28

2 answers

Tak, to legalne . Odpowiedni tekst znajduje się w §14.7.2/12, mówiący o jawnej instancji szablonu:

12 zwykłe reguły sprawdzania dostępu nie mają zastosowania do nazw używanych do określania jawnych instancji. [Uwaga: w szczególności argumenty i nazwy szablonów używane w deklaratorze funkcji (w tym typy parametrów, typy zwrotne i specyfikacje WYJĄTKÓW) mogą być typami prywatnymi lub obiektami, które normalnie nie byłyby dostępne i szablon może być szablonem członka lub funkcją członka, która normalnie nie byłaby dostępny. - Uwaga końcowa ]

Emhpasis mine.

 13
Author: GManNickG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-28 12:35:52

Kod jest wyraźnie nielegalny (i wymaga diagnostyki w czasie kompilacji). W linii:

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

Wyrażenie A::a uzyskuje dostęp do prywatnego członka A.

Standard jest o tym bardzo jasny: "Kontrola dostępu jest stosowana jednolicie do wszystkich nazw, niezależnie od tego, czy nazwy odnoszą się do deklaracje lub wyrażenia."(§11/4, podkreślenie dodane). Ponieważ a jest nazwą prywatną w A, wszelkie odniesienia do niej poza A są nielegalne.

 5
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-28 12:32:45