如何将lambda函数的参数转换并存储在std::function中。

huangapple go评论102阅读模式
英文:

How can I convert a lambda function arguments and store it in std::function

问题

我有一个存储在向量中的函数列表:

  1. std::vector<std::function<void(uint32_t)>> mFunctions;

我想要添加一个函数作为公共API,该函数接受不同的参数但将其转换为uint32_t:

  1. enum class MyHandle : uint32_t { Null = 0; };
  2. void addFunction(std::function<void(MyHandle)>&& fn) {
  3. mFunctions.push_back(fn);
  4. }

我该如何实现这一目标?

英文:

I have a list of functions stored in a vector:

  1. std::vector&lt;std::function&lt;void(uint32_t)&gt;&gt; mFunctions;

I want to add a function as a public API that accepts a different argument but casts it to uint32_t:

  1. enum class MyHandle : uint32_t { Null = 0; };
  2. void addFunction(std::function&lt;void(MyHandle)&gt; &amp;&amp;fn) {
  3. mFunctions.push_back(fn);
  4. }

How can I achieve this?

答案1

得分: 6

你只需要自己进行转换并用lambda包装参数来调用函数:

  1. void addFunction(std::function<void(MyHandle)> fn) {
  2. mFunctions.push_back([fn = std::move(fn)](uint32_t value) {
  3. fn(MyHandle{ value });
  4. });
  5. }

既然我们已经在这个过程中,我建议addFunction方法应该是模板参数化的,以回调参数为模板参数。这样可以避免类型擦除的许多开销,因为你不需要两层std::function

  1. template <std::invocable<MyHandle> F>
  2. void addFunction(F&& fn) {
  3. mFunctions.push_back([fn = std::forward<F>(fn)](uint32_t value) {
  4. std::invoke(fn, MyHandle{ value });
  5. });
  6. }

如果你无法使用C++20,它会是这样:

  1. template <typename F>
  2. void addFunction(F&& fn) {
  3. mFunctions.push_back([fn = std::forward<F>(fn)](uint32_t value) {
  4. std::invoke(fn, MyHandle{ value });
  5. });
  6. }

这里是代码运行的示例

英文:

You simply have to do the cast yourself and invoke the function with the casted argument by wrapping it in a lambda:

  1. void addFunction(std::function&lt;void(MyHandle)&gt; fn) {
  2. mFunctions.push_back([fn = std::move(fn)](uint32_t value) {
  3. fn(MyHandle{ value });
  4. });
  5. }

Since we're already at it, I would recommend that the addFunction method should be a template parameterized on the callback argument. This way you prevent a lot of overhead of the type erasure, since you don't have two layers of std::function:

  1. template &lt;std::invocable&lt;MyHandle&gt; F&gt;
  2. void addFunction(F&amp;&amp; fn) {
  3. mFunctions.push_back([fn = std::forward&lt;F&gt;(fn)](uint32_t value) {
  4. std::invoke(fn, MyHandle{ value });
  5. });
  6. }

If you don't have access to C++20 it would look like this:

  1. template &lt;typename F&gt;
  2. void addFunction(F&amp;&amp; fn) {
  3. mFunctions.push_back([fn = std::forward&lt;F&gt;(fn)](uint32_t value) {
  4. std::invoke(fn, MyHandle{ value });
  5. });
  6. }

Here is an example of the code in action

huangapple
  • 本文由 发表于 2023年5月29日 16:39:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355828.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定