Git Product home page Git Product logo

access_private_20's Introduction

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:

  • It is part of a third-party software package and
    • Our build system would overwrite the changes we made
    • We don't want to maintain our version
  • Touching the internals would require a tremendous amount of recompilation of client codes, which might not be desired.

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);
}
  • You can call private member and static private functions, overloaded functions without macro keeping noexcept signature.
  • You can also access static private variables without macro.
  • You can invoke private operators, conversion operators and variadic functions without macro.
  • You can invoke private constructors and the destructor.
  • You can invoke private member functions with the default arguments.
  • You can get private derived class addresses.
  • You can get lambda's captured variables.

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

  • We cannot access private reference members. (See this issue.) On clang this could be solved.
  • On MSVC, we cannot call private constructors/destructors, we cannot access the default arguments of the private functions, and we can get limited only the private base class address (is_pointer_interconvertible_base_of with reinterpret_cast). (See issue 1 issue 2.)
  • On GCC, we can get limited only the private base class address (is_pointer_interconvertible_base_of with reinterpret_cast). (See this issue.)
  • On Clang, we cannot get lambda's captured variables, because of the implementation: the captured variables are unnamed implicit members.
  • We have a link-time error in case of only in-class declared const static variables if used as reference/pointer (or in debug build). That's because we'd take the address of that, and if that is not defined (i.e. the compiler does a compile-time insert of the const value), we'd have an undefined symbol. This can be workarounded with macro.

Compilers

I have done tests for the following compilers:

  • LLVM version 16
  • GCC
    • 13.2
    • 12.3
  • MSVC

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.

access_private_20's People

Contributors

martong avatar schaumb avatar survivalizeed avatar yuantailing avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

gmh5225 jnulzl

access_private_20's Issues

Cannot able to get private member behind base class

example:

using VD = std::variant<double, std::string_view>;
template struct access_private::access<&VD::_M_index>; 

... 

VD vd;
accessor<"_M_index">(vd); // fail, because this member is hidden behind private base class

Get the memptr/funptr exact defined class

The exact class is hidden if you want to access some function/member at any base class.

using VD = std::variant<double, std::string_view>;
template struct access_private::access<&VD::_M_index>; 

This member pointer resolved as unsigned char std::__detail::__variant::_Variant_storage_alias<double, std::string_view>::* and not unsigned char VD::*. Currently, it cannot be queried.

It can be a nice feature that gets the exact member pointer's class:

template struct access_private::type_access_at<&VD::_M_index>;

using base_class = access_private::type_accessor_at<"_M_index">;
using result_class = access_private::type_result_at<"_M_index">;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.