Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Accessing Private Data
#include <iostream>
// This is a rewrite and analysis of the technique in this article:
// http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
// ------- Framework -------
// The little library required to work this magic
// Generate a static data member of type Tag::type in which to store
// the address of a private member. It is crucial that Tag does not
// depend on the /value/ of the the stored address in any way so that
// we can access it from ordinary code without directly touching
// private data.
template <class Tag>
struct stowed
{
static typename Tag::type value;
};
template <class Tag>
typename Tag::type stowed<Tag>::value;
// Generate a static data member whose constructor initializes
// stowed<Tag>::value. This type will only be named in an explicit
// instantiation, where it is legal to pass the address of a private
// member.
template <class Tag, typename Tag::type x>
struct stow_private
{
stow_private() { stowed<Tag>::value = x; }
static stow_private instance;
};
template <class Tag, typename Tag::type x>
stow_private<Tag,x> stow_private<Tag,x>::instance;
// ------- Usage -------
// A demonstration of how to use the library, with explanation
struct A
{
A() : x("proof!") {}
private:
char const* x;
};
// A tag type for A::x. Each distinct private member you need to
// access should have its own tag. Each tag should contain a
// nested ::type that is the corresponding pointer-to-member type.
struct A_x { typedef char const*(A::*type); };
// Explicit instantiation; the only place where it is legal to pass
// the address of a private member. Generates the static ::instance
// that in turn initializes stowed<Tag>::value.
template class stow_private<A_x,&A::x>;
int main()
{
A a;
// Use the stowed private member pointer
std::cout << a.*stowed<A_x>::value << std::endl;
};
@come-raczy

This comment has been minimized.

Copy link

come-raczy commented Aug 27, 2013

why having several layers of classes and static members instead of a single class with static method like this:

template <class Type, Type value>
struct accessor
{
    static Type getValue() {return value;}
};

It seems to work (at least with gcc 4.8.1 using c++11)

@polkovnikov-ph

This comment has been minimized.

Copy link

polkovnikov-ph commented Aug 29, 2014

@come-raczy That's an incorrect behaviour. You cannot pass pointer to private member anywhere except the arguments for explicit instantiation.

@garethsb

This comment has been minimized.

Copy link

garethsb commented May 14, 2015

(Revised 13-Oct-2016!)

This technique can also be used to access private static member variables.

E.g.

struct B
{
private:
    static char const* x;
};

char const* B::x = "proof!";

struct B_x { typedef char const** type; };
template class stow_private<B_x,&B::x>;

int main()
{
        // Use the stowed private static member pointer
        std::cout << *stowed<B_x>::value << std::endl;
};
@mdadams

This comment has been minimized.

Copy link

mdadams commented Feb 2, 2017

@dabrahams Just for fun, I tried a variation on the ideas from your code example using variable templates:
https://gist.github.com/mdadams/98710ba3478f306633df20dca47d5cd9
The code in my example works okay with GCC 6.3.0, but Clang 3.9.1 yields undefined references to saved_private_v<Widget_i_> and saved_private_v<Widget_f_> when linking. I am not sure if this is a bug in Clang or I am making some non-portable assumptions about templates in my code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.