Skip to content

Instantly share code, notes, and snippets.

@correosdelbosque
Forked from dabrahams/private_access.cpp
Created October 29, 2016 06:42

Revisions

  1. @dabrahams dabrahams revised this gist Jan 14, 2012. 1 changed file with 10 additions and 4 deletions.
    14 changes: 10 additions & 4 deletions private_access.cpp
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,11 @@
    #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
    @@ -27,18 +33,18 @@ 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

    // Demonstration type with private data
    struct A
    {
    A() : x("proof!") {}
    private:
    char const* x;
    };

    // A tag type for A::x. Each distinct private member should have its
    // own tag. Each tag should contain a nested ::type that is the
    // corresponding pointer-to-member type.
    // 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
  2. @dabrahams dabrahams created this gist Dec 28, 2011.
    55 changes: 55 additions & 0 deletions private_access.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    #include <iostream>

    // 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 -------

    // Demonstration type with private data
    struct A
    {
    A() : x("proof!") {}
    private:
    char const* x;
    };

    // A tag type for A::x. Each distinct private member 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;
    };