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

元气小坏坏 提交于 2020-01-04 03:58:26

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/44015883/how-to-pass-template-function-with-default-arguments-to-stdcall-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!