How to force a static member to be initialized?
Consider:
template<typename T, T> struct value { };
template<typename T>
struct HasStatics {
static int a; // we force this to be initialized
typedef value<int&, a> value_user;
};
template<typename T>
int HasStatics<T>::a = /* whatever side-effect you want */ 0;
It's also possible without introducing any member:
template<typename T, T> struct var { enum { value }; };
typedef char user;
template<typename T>
struct HasStatics {
static int a; // we force this to be initialized
static int b; // and this
// hope you like the syntax!
user :var<int&, a>::value,
:var<int&, b>::value;
};
template<typename T>
int HasStatics<T>::a = /* whatever side-effect you want */ 0;
template<typename T>
int HasStatics<T>::b = /* whatever side-effect you want */ 0;
We can use a simple trick based on a declaration that must be instantiated with the class:
template<…>
struct Auto {
static Foo foo;
static_assert(&foo);
};
template<…> Foo Auto::foo=…;
Note that some compilers warn about the comparison to null; that can be avoided with &foo==&foo
, (bool)&foo
, or ((void)&foo,true)
if needed.
Note also that GCC 9.0–9.2 don’t count this as an odr-use.