How to use a private member from outside the class
Am I missing some subtle mechanism by which “unused” private members might actually be referenced from other TUs?
Indeed, I was! Check this out (Godbolt):
struct S {
private:
static int private_static_data;
};
int S::private_static_data = 42; // Optimize this away?
// Meanwhile, in some other TU...
static int *f();
template<int *x>
struct F {
friend int *f() { return x; }
};
template struct F<&S::private_static_data>;
int steal_private_data() {
return *f();
}
According to [temp.spec]/6,
the template arguments of explicit instantiation declarations are permitted
to name “private types or objects that would normally not be accessible” —
such as S::private_static_data
in this case.
So we can instantiate F<&S::private_static_data>
, even though we cannot
actually refer to that instantiation by name afterwards. This “leaks” the
private data of S
into F
. F
leaks it out again via the global function
f()
. And then anyone can call f()
to obtain a pointer to S
’s private
data.
Therefore, although the compiler of TU #1 can see that none of S
’s members and
friends use S::private_static_data
, it cannot conclude that
the definition of S::private_static_data
is unused. Other object files
may indeed refer to that linker symbol. So the compiler must generate code for it.