Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access private member using template trick

Tags:

c++

templates

From a blog post Access to private members: Safer nastiness by Johannes Schaub - litb:

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

how get function can be call from a object since its not defined inside class A ?

EDIT:

I don't understand why get must have Tag as parameter instead of a.*get<A_f>() => ok it's due to ADL mechanism

like image 984
Guillaume Paris Avatar asked Oct 20 '12 22:10

Guillaume Paris


People also ask

How do I access private members?

Private: The class members declared as private can be accessed only by the member functions inside the class. They are not allowed to be accessed directly by any object or function outside the class. Only the member functions or the friend functions are allowed to access the private data members of the class.

Can an object access private members?

This is perfectly legal. Objects of the same type have access to one another's private members. This is because access restrictions apply at the class or type level (all instances of a class) rather than at the object level (this particular instance of a class).

Can we access private data members of a class without using a member or a friend function in C ++?

In C++, a friend function or friend class can also access private data members. So, is it possible to access private members outside a class without friend? Yes, it is possible using pointers.

How can we access private method of a class from outside the class C++?

We can access private method in other class using the virtual function, A virtual function is a member function which is declared within a base class and is re-defined (Overridden) by a derived class.


3 Answers

You are not calling get from a! Actually what get return is a class pointer to a member inside A and type of it is int A::* so you need an instance of A to access that value.

For example let me play a little with your code:

struct A {
    A(int a):a(a) { }
    int b;
private:
    int a;
};
void test() {
    auto p = &A::b;
    std::cout << a.*p << std::endl;
}

Did I call p from inside a? a does not have p, this is exactly what happened in your code, get function return &A::a and you use a to read its value! that's all, nothing is wrong and I think it will be compiled in all compilers.

One other question here is: Why C++ allow declaring template using private member of A. C++ standard say:

14.7.2p8 The usual access checking rules do not apply to names used to specify explicit instantiations. [Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible.]

But if you try to instantiate or even typedef specified template then you get an error. Let's modify your example slightly:

struct A {
private:
    int a;
    friend void f();
};

// Explicit instantiation - OK, no access checks
template struct Rob<A_f, &A::a>;

// Try to use the type in some way - get an error.
struct Rob<A_f, &A::a> r;            // error
typedef struct Rob<A_f, &A::a> R;    // error
void g(struct Rob<A_f, &A::a>);      // error

// However, it's Ok inside a friend function.
void f() {
    Rob<A_f, &A::a> r;               // OK
    typedef Rob<A_f, &A::a> R;       // OK
}
like image 172
BigBoss Avatar answered Nov 03 '22 21:11

BigBoss


It's legal because friend functions are always in the global scope, even if you implement them inside a class. In other words, this:

class A
{
    friend void go() {}
};

is just a shortcut for:

class A
{
    friend void go();
};

void go() {}
like image 33
user1610015 Avatar answered Nov 03 '22 20:11

user1610015


This is a known compiler bug in gcc and was fixed in a later release. See-:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437

like image 38
bootkick Avatar answered Nov 03 '22 19:11

bootkick