user26862880
user26862880

Reputation: 33

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.

Upvotes: 3

Views: 84

Answers (1)

user12002570
user12002570

Reputation: 1

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

Upvotes: 1

Related Questions