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:

  1. Template instantiation: Using template instantiation to initialize a static member pointer
  2. Compile-time initialization: Leveraging compile-time initialization to store the private member pointer
  3. Static storage: Storing the member function pointer in a static variable accessible from outside
  4. 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.