2012-03-28 9 views
13

Unser berüchtigter litb hat einen interessanten Artikel über how to circumvent the access check.Mai Zeiger auf Mitglieder umgehen die Zugriffsebene eines Mitglieds?

Es ist voll von diesem einfachen Code demonstriert:

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

Welche und läuft (Ausgang 42) kompiliert mit gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 und kompiliert mit Clang 3.0 und Comeau C (user1131467 Kommentar sehen)/C++ 4.3.10.1 in C++ 03 Strict-Modus und MSVC 2005

ich von Luchian auf this answer, in dem ich sie gefragt wurde verwendet, um zu rechtfertigen, dass es tatsächlich legal war. Ich stimme Luchian zu, dass es komisch ist, aber sowohl Clang als auch Comeau sind enge Konkurrenten für die meisten "Standard" -Compiler (viel mehr als MSVC standardmäßig) ...

Und ich konnte nichts in den Entwürfen finden von den Standards, die ich zur Verfügung habe (n3337 ist die letzte Version, die ich in die Finger bekam).

Also ... kann jemand tatsächlich rechtfertigen, dass es legal ist oder nicht?

+0

FYI Dies gibt 'proof: 42' mit' g ++ - 4.7 (Debian 4.7.0-1) 4.7.0' sowohl in -std = C++ 11' als auch in -std = gnu ++ 11' –

+0

aus Entschuldigung, das ist mein Fehler. Das kompiliert, was nicht kompiliert wurde, war http://stackoverflow.com/a/6886432/673730 - und ich versuchte, auf eine private Funktion zuzugreifen, nicht Datenmitglied. –

+0

BTW Ich bin immer noch auf der Suche nach einer Antwort darauf, wenn die Antwort funktioniert, wäre es genau das, wonach ich gesucht habe, aber es tut es nicht. –

Antwort

13

Ja, es ist legal. Der entsprechende Text ist bei §14.7.2/12, im Gespräch über explizite Template-Instantiierung:

12 Der üblicher Zugang Prüfregeln gilt nicht für die Namen explizit instantiations verwendet angeben. [] Hinweis:: Insbesondere die im Funktionsdeklarator verwendeten Template-Argumente und Namen (einschließlich Parametertypen, Rückgabetypen und Ausnahmespezifikationen) können private Typen oder Objekte sein, auf die normalerweise nicht zugegriffen werden kann, und die Vorlage kann eine Membervorlage oder sein Mitgliedsfunktion, die normalerweise nicht zugänglich wäre. - Endnote]

Emhpasis Mine.

+4

Ah! Das ist wahrscheinlich das, was ich an der Norm am meisten mag, um eine umfassende Sicht auf etwas zu haben, man muss nur durch die ganze Sache stapfen und die Teile zusammenfügen. –

+1

@MatthieuM .: Aber das ist auch der Grund, warum ich den Standard hasse! :) EDIT: Whoosh! – GManNickG

+0

Das sollte ironisch sein;) Obwohl jetzt, wo es ein GitHub ist, könnten wir vielleicht einen Schnitt vorschlagen, um diesen Paragraphen von dem zitierten James zu vernetzen! –

5

Der Code ist eindeutig illegal (und erfordert eine Kompilierzeitdiagnose). In der Zeile:

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

der Ausdruck A::a greift auf ein eigenes Mitglied A.

Der Standard ist sehr klar darüber: “ Zutrittskontrolle gleichmäßig auf alle Namen angelegt wird, ob die Namen von Erklärungen oder Ausdrücke bezeichnet werden. “ (§11/4, Hervorhebung hinzugefügt). Da a ein privater Name in A ist, ist jede Bezugnahme darauf außerhalb von A illegal.

+3

Es ist eigentlich nicht illegal, eine Ausnahme wird später für explizite Template-Instanziierungen hinzugefügt. Das "All" dort ist offensichtlich irreführend, es ist "alles, wenn nicht anders angegeben". Ich werde nicht ablehnen, weil es ziemlich unintuitiv ist. – GManNickG

+0

@GManNickG Eigentlich ist es nicht klar, und ich denke, eine DR ist in Ordnung. In der Standard, "alle" bedeutet "alle", nicht "alle, sofern nicht anders angegeben", und der Kontext in §14.7.2 kann andere Interpretationen zulassen (obwohl sie sind nicht sehr natürlich). Das sieht nach einem Widerspruch aus, was bedeutet, dass ein DR in Ordnung ist. –

+0

Sie haben Recht, es gibt keine Notwendigkeit für diese Qualifikation, um dort zu sein. – GManNickG

Verwandte Themen