Search code examples
c++templatesc++11initializationclass-template

Is there a way to call an initialization function only when specific class template (specialization) is instantiated?


I'm designing a wrapper over various computational functionality. Some of the underlying backends require some init functions to be called before any other API calls are made. I could use some static variable that is initialized before main, and wrap it in some function as described here so that I can catch any errors produced during initialization.

I wonder if there is a better way to handle this. Note that there will never be an instance of the class template, as everything is either a typedef or static member.


Solution

  • To address the problem of initializing the API only for some specializations, and of initializing it only once, I'd do something like this:

    #include <iostream>
    
    template <typename T>
    struct Wrapper
    {
        // class who will be statically instantiated
        struct CtorClass
        {
            CtorClass()
            {
                std::cout << "Init\n";
            }
        };
    
        static CtorClass static_ctor;
    
        static void compute1(){}
        static void compute2(){}
    
    };
    
    // definition for template static member cons
    template <typename T>
    typename Wrapper<T>::CtorClass Wrapper<T>::static_ctor;
    
    struct NeedInit{};
    
    // you will have to use static_ctor in every funcition of the
    template <>
    void Wrapper<NeedInit>::compute1()
    {
        static_ctor;
    }
    
    template <>
    void Wrapper<NeedInit>::compute2()
    {
        static_ctor;
    }
    
    int main()
    {
        Wrapper<int>::compute1();
        Wrapper<int>::compute2();
        Wrapper<NeedInit>::compute1();
        Wrapper<NeedInit>::compute2();
    }
    

    Sadly, this way you have to use static_ctor in every function specialization that belongs to a Wrapper<NeedInit> class. But you wouldn't need to check for the initialization to have already been called.

    Then, you could catch errors like you said.