Consider this example code:
template
char register_(){
return D::get_dummy(); // static function
}
template
struct Foo{
Is there any way to force dummy to be initialized (effectively calling register_) without any instance of Bar or Foo (no instances, so no constructor trickery)?
Wouldn't this be sufficient?
std::cout << Foo<int>::dummy;
Something like that comes to my mind:
// in some c++ file (to make i with internal linkage)
static int i = init_dummy(Foo<int>::dummy);
where init_dummy is defined like this:
int init_dummy(...)
{
return 1;
}
Due to variable args you can put more initializations there like:
static int i = init_dummy(Foo<int>::dummy, Foo<double>::dummy, Foo<whatever>::dummy);
How are you checking the value set by Bar. I changed your code and added another function in bar as:
....
static char const get_dummy(int){return Foo<Bar>::dummy;}
....
and it is giving me exactly the expected result. I may not be understanding correctly, what do you exactly want to achieve ?
Static members are shared among the objects so their scope must be resolved at access. that is why we use :: by telling compiler explicitly that this is the member of the class we want to access.
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.
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;