Access Private Members
A C++ technique for accessing private member functions using template metaprogramming without violating language rules.
The Problem
Sometimes during debugging or testing, you need to access private members of a class. While #define private public works, it’s a language violation and not a clean solution.
The Template Solution
Here’s a template-based approach that uses static initialization to store a pointer to a private member function:
template<typename type>
struct access {
inline static type member_pointer;
};
template<typename type, type pointer>
struct create_access : access<type> {
struct assign_pointer {
assign_pointer() { access<type>::member_pointer = pointer; }
};
inline static assign_pointer by_calling_default_ctor;
};
Example Usage
Consider a struct with a private method:
struct Alexander {
private:
void quote() {
std::cout << "I am not afraid of an army of lions led by a sheep; "
<< "I am afraid of an army of sheep led by a lion.\n";
}
};
To access the private quote() method:
using type = void(Alexander::*)();
template struct create_access<type, &Alexander::quote>;
int main() {
Alexander S;
(S.*access<type>::member_pointer)();
}
How It Works
The technique works by:
- Template instantiation: Using template instantiation to initialize a static member pointer
- Compile-time initialization: Leveraging compile-time initialization to store the private member pointer
- Static storage: Storing the member function pointer in a static variable accessible from outside
- Function call: Calling the member function through the stored pointer
Important Notes
- This technique is standards-compliant (no undefined behavior)
- It works because the template instantiation happens during compilation
- The private member access happens at the template instantiation point where it’s legal
- Credit goes to litb’s blog post and Herb Sutter’s GotW #76 for inspiration
Use Cases
This technique is primarily useful for:
- Unit testing private methods
- Debugging complex class interactions
- Accessing private functionality in legacy code
- Educational purposes to understand template metaprogramming
While this technique is clever and standards-compliant, use it judiciously and consider whether your design might benefit from better encapsulation or friendship declarations.