Our infamous litb has an interesting article on how to circumvent the access check.
It is fully demonstrated by this simple code:
#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;
}
Which compiles and runs (output 42
) with gcc 4.3.4, gcc 4.5.1, gcc 4.7.0 (see user1131467's comment) and compiles with Clang 3.0 and Comeau C/C++ 4.3.10.1 in C++03 strict mode and MSVC 2005.
I was asked by Luchian on this answer in which I used it to justify that it was actually legal. I agree with Luchian that it is weird, however both Clang and Comeau are close contenders for the most "Standard" compilers available (much more so than MSVC by default)...
And I could not find anything in the drafts of the Standards I have available (n3337 being the last version I got my hands on).
So... can anyone actually justifies that it is legal or not ?
proof:42
withg++-4.7 (Debian 4.7.0-1) 4.7.0
in both-std=c++11
and-std=gnu++11
– Mistreat