c++templatessingletonstd-call-once

Why std::call_once deduction failed and the error is "couldn’t deduce template parameter ‘_Callable’ "


I am trying to use singleton pattern with std::call_once, but template dedution failed while compiling.

template<typename T>
class Singleton_4
{

public:
    template<typename...Args>
    static void  create(Args&&...args) {
        tPtr = new T(std::forward<Args>(args)...);
    }   
public:
    template<typename...Args>
    static T* instance(Args&&...args) {
        std::call_once(flag, &Singleton_4::create, std::forward<Args>(args)...);
        return tPtr;
    }   

public: 
    Singleton_4() = default;
    Singleton_4(const Singleton_4&) = delete;
    Singleton_4(Singleton_4&&) = delete;
    Singleton_4& operator=(const Singleton_4&) = delete;
    Singleton_4& operator=(Singleton_4&&) = delete;

private:
    inline static T* tPtr;
    inline static std::once_flag flag;

};

I want to know what happened and how to resolve this problem.


Solution

  • The problem is that create is a function template not an actual function. And we can't take an address of a template. Instead we need to take the address of the instantiated function from the function template.

    This can be done by specifying the template argument explicitly as shown below:

    Solution

    template<typename...Args>
        static T* instance(Args&&...args) {
    //------------------------------------------------vvvvvvv---->passed Args explicitly to make it clear that we are taking address of an instantiation
            std::call_once(flag, &Singleton_4::create<Args...>, std::forward<Args>(args)...);
            return tPtr;
        }
    

    Working demo