schaumb / access_private_20

Access private members and statics of a C++ class
MIT License
8 stars 2 forks source link

Introduction

This library is a collection of template hacks to access private members. Why would you need this? Testing. There are some cases when we want to test a class, but we can't or don't want to modify it. The reasons behind that might be the following:

Why not use #define private public? Because that's undefined behavior. The C++ standard states that the relative order of members in a class with different access specifiers is undefined.

Usage

class A {
  int m_i = 3;
  int m_f(int p) { return 14 * p; }
};

template struct access_private::access<&A::m_i>;

void foo() {
  A a;
  auto &i = access_private::accessor<"m_i">(a);
  assert(i == 3);
}

template struct access_private::access<&A::m_f>;

void bar() {
  A a;
  auto res = access_private::accessor<"m_f">(a, 3);
  assert(res == 42);
}

For DETAILED USAGE and EXAMPLES, please take a look at test.cpp and new_tests.cpp!

How does it work?

The ISO C++ standard specifies that there is no access check in case of explicit template instantiations (C++14 / 14.7.2 para 12). We can exploit this by defining a static pointer to a member (or a friend function), which holds (returns) the address of the private member. References:

Limitations

Compilers

I have done tests for the following compilers:

Test code is compiled with -std=c++20.

Notes

There is a C++ standard issue that says:

Stateful metaprogramming via friend injection techniques should be ill-formed

The ::access_private::accessor_t<...> template class implements a friend function get(), which is used after the class definition. I am not sure, however, if that issue has been ever fixed.