How to force a static member to be initialized?

后端 未结 5 1545
悲&欢浪女
悲&欢浪女 2020-11-27 05:46

Consider this example code:

template
char register_(){
    return D::get_dummy(); // static function
}

template
struct Foo{
           


        
相关标签:
5条回答
  • 2020-11-27 05:48

    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;
    
    0 讨论(0)
  • 2020-11-27 05:57

    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);
    
    0 讨论(0)
  • 2020-11-27 06:01

    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.

    0 讨论(0)
  • 2020-11-27 06:08

    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.

    0 讨论(0)
  • 2020-11-27 06:11

    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;
    
    0 讨论(0)
提交回复
热议问题