Search code examples
c++unit-testingprivate-members

Access a private static member outside the class


Non-static private members can be hacked into like so, but what about static members?

class Foo {
private:
    static std::vector<int> secrets;
}

Suppose I want to test Foo and I need to get at or change the private static stuff. If it's supposed to stick around as a permanent unit test, it would make sense to just declare friend class FooTest;, but maybe it's not so permanent and I prefer to keep things clean. Or maybe I just can't edit Foo for whatever reason. Can I hack it?


Solution

  • Can I hack it?

    Yes, even though it is trivial to modify this answer for static member instead of a non-static member, here is the working modified example. The only thing that is different here from the original answer is the syntax used for a static field. Everything else is the same as the original answer.

    #include <iostream>
    #include <vector> 
    class Foo {
    private:
        static std::vector<int> secrets;
    };
    std::vector<int> Foo::secrets = {1,1,1};
    
    // tag used to access Foo::member
    struct Foo_member { 
      
      using type = std::vector<int>*;
      friend type get(Foo_member);
    };
    template<typename Tag, typename Tag::type M>
    struct Rob { 
      friend typename Tag::type get(Tag) {
        return M;
      }
    };
    //explicit instantiation
    template struct Rob<Foo_member, &Foo::secrets>;
    
    int main() {
      std::cout << "Before: ";
      for(const auto &elem: *get(Foo_member()))  
      { 
         std::cout << elem << " ";
      } 
      *get(Foo_member()) = {4,2,6}; //overwrite the private field's value!!
      std::cout << "\nAfter: " ;
      for(const auto &elem: *get(Foo_member()))  
      { 
         std::cout << elem << " ";
      }
    }
    

    Working demo


    You can also use lvalue reference instead of pointers in the above example so that you don't have to dereference the result of get again and again. Demo with lvalue reference instead of pointer