C++17如何保存泛型可调用对象以备后用

tyu7yeag  于 2022-11-27  发布在  其他
关注(0)|答案(3)|浏览(101)

我想保存一个泛型可调用对象及其状态以备后用。请参见下面的示例代码。我可能会使用std::functionstd::bind来实现此操作,但我不知道哪种方法最好。另外请注意,在下面示例的main()中,capturedInt必须保存在可调用对象的状态中。
有哪些可能性:

  • makeCallable(fun, args...) { ... }
  • CallableType
template <typename RetT>
class Service
{
public:

   template <typename Fn, typename... Args>
   Service(Fn&& fun, Args&&... args)
   {
      m_callable = makeCallable(fun, args...);
   }

   Run()
   {
      m_callable();
   }

   CallableType<RetT> m_callable;
};

// Template deduction guides (C++17)
template <typename Fn, typename... Args>
Service(Fn&& fun, Args&&... args) -> Service<std::invoke_result_t<std::decay_t<Fn>, std::decay_t<Args>...>>;

int main()
{
   Service* s = nullptr;
   {
      int capturedInt = 5;
      s = new Service([capturedInt]() { std::cout << capturedInt << std::endl; } );
   }
   
   s->Run();
}
2wnc66cl

2wnc66cl1#

我也会使用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();

.那么就不用担心终身上课引起的时间问题了。

2lpgd968

2lpgd9682#

在给定的设置下,m_callable的唯一选项是std::function,因为函子的类型是构造函数本身的参数,所以必须对函子执行类型擦除操作以保存它供将来使用--而std::function正是实现这一点的一种机制。
因此,m_callable将为:

std::function<retT ()> m_callable;

您可以将其设置为:

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

3zwtqj6y3#

除了std::function<>std::bind之外,还有一种叫做continuation passing的模式。代价是,您需要将代码的其余部分 Package 在lambda中:

template<typename Cont>
void get_plus2_cps(Cont cont) {
    auto plus2 = [&](auto n) { return n + 2; };
    cont(plus2);
}

// usage:
int main() {
    // some code
    get_plus2_cps([&](auto plus2) {
        // rest of the code here
        std::cout << plus2(2) << ' ' << plus2(2.0) << std::endl;
    };
    // no code here
}

相关问题