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?
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 << " ";
}
}
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