简体   繁体   中英

How to pass template function with default arguments to std::call_once

I need to use std::call_once in my templatized singleton class but currently below sample code is not compiling :

std::once_flag flag;
class LifeTrackerHelper
{
public:
template<class T>
inline static int SetLongevity(std::unique_ptr<T>& pobj,unsigned int longevity = 0)
{
    return 0;
}
};
template<class T>
class Singleton
{
   public:    
   inline static T* getInstance()
   {
     static std::unique_ptr<T> ptr(new T());  
     std::call_once(flag,&LifeTrackerHelper::SetLongevity<T>,ptr);  
     //static int i = LifeTrackerHelper::SetLongevity<T>(ptr);
     // if call_once is commented and above line uncommented this will work
     return ptr.get();
   }
};
class Test
{
    public:
    void fun()
    {
        std::cout<<"Having fun...."<<std::endl;
    }
};
int main()
{

  Singleton<Test>::getInstance()->fun(); 
}

So need help in understanding how to properly use std::call_once here.

Your problem is &LifeTrackerHelper::SetLongevity<T> is a function pointer expecting a unique_ptr and an unsigned int , but it only gets the one argument. While the actual function has a default value for the second argument, it needs both arguments when called by a function pointer.

You can fix it by passing another argument:

std::call_once(flag, &LifeTrackerHelper::SetLongevity<T>, ptr, 0);

Or you can wrap it in a lambda:

std::call_once(flag, [](std::unique_ptr<T>& p){ return LifeTrackerHelper::SetLongevity<T>(p); }, ptr);

According to cppreference , before C++17 the arguments to call_once will be copied or moved. So far, I haven't gotten any errors passing a unique_ptr , but it might be wise to use std::ref on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM