【问题标题】:How to pass template function with default arguments to std::call_once如何将具有默认参数的模板函数传递给 std::call_once
【发布时间】:2017-10-16 09:16:51
【问题描述】:

我需要在我的模板化单例类中使用 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,问题有什么问题吗??
  • flag的声明在哪里?你到底想在这里做什么?
  • 感谢我在示例中添加了标志,我只是想修改我的同事创建的通用单例
  • 问题是ptr 传递给call_once。我假设call_once 将尝试调用std::unique_ptr 的复制构造函数,这将导致错误,因为std::unique_ptr 的复制构造函数被删除。不过我还没有测试过。
  • 我尝试在 unique_ptr 上使用 std::ref 但这也不起作用

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


【解决方案1】:

您的问题是 &amp;LifeTrackerHelper::SetLongevity&lt;T&gt; 是一个函数指针,需要 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

【讨论】:

  • 但是为什么我们在使用函数指针时甚至需要传递默认参数
  • 使用 c++11 时我需要使用 std::ref 否则会出现编译错误cpp.sh/3p3mv
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
相关资源
最近更新 更多