如何使用默认参数将模板函数传递给std :: call_once

时间:2017-05-17 04:52:00

标签: c++ multithreading c++11 c++14

我需要在我的模板化单例类中使用std :: call_once,但目前下面的示例代码没有编译:

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(); 
}

所以需要帮助理解如何在这里正确使用std :: call_once。

1 个答案:

答案 0 :(得分:3)

您的问题是&LifeTrackerHelper::SetLongevity<T>是一个期望unique_ptrunsigned int的函数指针,但它只获得一个参数。虽然实际函数具有第二个参数的默认值,但在由函数指针调用时它需要两个参数。

您可以通过传递另一个参数来修复它:

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

或者你可以把它包装成lambda:

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

根据cppreference,在C ++ 17之前,call_once的参数将被复制或移动。到目前为止,我还没有通过unique_ptr传递任何错误,但在其上使用std::ref可能是明智之举。