【问题标题】:C++17 How to save a generic callable for later useC ++ 17如何保存通用可调用以供以后使用
【发布时间】:2020-10-13 18:55:17
【问题描述】:

我想保存一个带有其状态的通用可调用对象以供以后使用。请参阅下面的示例代码。我可能可以使用std::functionstd::bind 来实现这一点,但我不知道什么是最好的。另请注意,在下面示例的main() 中,capturedInt 必须保存在可调用的状态中。

有哪些可能性:

  • makeCallable(fun, args...) { ... }
  • CallableType
模板 
类服务
{
民众:

   模板 
   服务(Fn&& fun, Args&&... args)
   {
      m_callable = makeCallable(fun, args...);
   }

   跑步()
   {
      m_callable();
   }

   CallableType m_callable;
};

// 模板推导指南 (C++17)
模板 
服务(Fn&& fun, Args&&... args) -> 服务<:invoke_result_t>, std::decay_t...>>;

主函数()
{
   服务* s = nullptr;
   {
      int 捕获Int = 5;
      s = new Service([capturedInt]() { std::cout 运行();
}

【问题讨论】:

    标签: c++ generics stl c++17 callable


    【解决方案1】:

    我也会使用std::function,但将其作为类的接口,如下所示:

    template <typename RetT>
    class Service
    {
    public:
    
       Service(std::function<RetT()> fun)
       {
          m_callable = std::move(fun);
       }
    
       Run()
       {
          m_callable();
       }
    private:
       std::function<RetT()> m_callable;
    };
    

    然后,您将明确存储类的可调用对象的选项。然后,用户可以决定如何将他们的参数绑定到自己的可调用对象上,这对于 std::function 来说是灵活的。

    s = new Service([capturedInt]() { std::cout << capturedInt << std::endl; } );
    s->Run();
    

    struct Foo
    {
        void MyPrint(int capturedInt) { std::cout << capturedInt << std::endl; }
    };
    Foo foo;
    int capturedInt = 5;
    s = new Service(std::bind(&Foo::MyPrint, &foo, capturedInt);
    s->Run();
    

    。那么你就不用担心类导致的终身问题了。

    【讨论】:

      【解决方案2】:

      根据设置,m_callable 的唯一选择是std::function。由于函子的类型是构造函数本身的参数,因此您必须对函子进行类型擦除以保存以供将来使用 - 而std::function 只是一种机制。

      因此,m_callable 将是:

      std::function<retT ()> m_callable;
      

      你会这样设置:

      m_callable = [=]() { return fun(args...); }
      

      【讨论】:

      • 为什么不使用auto
      • 虽然我同意 std::function 是唯一的类型,如果 FnArgs... 对于一种返回类型可能不同,您对 m_callable 的构造没有使用完美转发。例如,您不能传递像 str::unique_ptr 这样的仅移动类型。我实际上会使用std::bind,因为完美的转发参数和调用函数以及通过 lambda 捕获是不平凡的。但是m_callable = std::bind(std::forward&lt;Fn&gt;(fun), std::forrward&lt;Args&gt;(args)...); 应该是一种享受。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      • 2020-09-15
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多