A direct static data member that's assigned to needs a definition. Basically the definition allocates memory. Goes like this:
class C
{
private:
static int i; // pure declaration
public:
static auto n_instances() -> int { return i; }
~C() { --i; }
C(){ ++i; }
C( C const& ) { ++i; }
};
int C::i; // definition
In a header file that is impractical (if the header is used in multiple translation units it will be in violation of the One Definition Rule, with the linker complaining), so then you can use the following technique:
class C
{
private:
static auto n()
-> int&
{
static int the_count = 0;
return the_count;
}
public:
static auto n_instances() -> int { return n(); }
~C() { --n(); }
C(){ ++n(); }
C( C const& ) { ++n(); }
};
There are also other ways to do this, including the template trick and C++17 inline data.
I chose to use int instead of unsigned because int is good for integer numbers, while unsigned is good for bit-level stuff, but not vice versa.
Disclaimer: code not touched by compiler.