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

C++17 How to save a generic callable for later use

本文关键字:对象 调用 泛型 何保存 保存 C++17      更新时间:2023-10-16

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

有哪些可能性:

  • makeCallable(fun, args...) { ... }
  • CallableType
模板<类型名称 RetT=">类服务 { 公共:  模板<类型名>服务(Fn&& fun, Args&&...参数(  { m_callable = makeCallable(fun, args...(;  }  运行((  { m_callable((;  }  可调用类型m_callable; }; 模板演绎指南 (C++17( 模板<类型名>服务(Fn&& fun, Args&&...args( -> Service<std::invoke_result_t><std::d>, std::d ecay_t...>>; int main(( {  服务* s = 空点;  { int capturedInt = 5; s = new Service([capturedInt](( { std::cout <<capturedInt <<std::endl; } (;  }  s->Run((; }

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

.这样你就不用担心上课带来的终身问题了。

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

因此,m_callable将是:

std::function<retT ()> m_callable;

你会这样设置它:

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

除了std::function<>std::bind,还有一种模式叫做延续传递。好处是,您还可以保存通用 lambda,这不适用于前两者;您付出的代价是,您需要将其余代码包装在 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
}