代码之家  ›  专栏  ›  技术社区  ›  user26862880

为什么std::call_once去噪失败,错误为“无法推断模板参数_Callable”

  •  1
  • user26862880  · 技术社区  · 1 年前

    我试图在std::call_once中使用单例模式,但在编译时模板删除失败。

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

    我想知道发生了什么,以及如何解决这个问题。

    1 回复  |  直到 1 年前
        1
  •  0
  •   user12002570    1 年前

    这个 问题 是吗 create 是一个函数模板,而不是一个实际的函数。我们无法获取模板的地址。相反,我们需要从函数模板中获取实例化函数的地址。

    这可以通过明确指定模板参数来实现,如下所示:

    解决方案

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

    Working demo