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.
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;
}