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

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

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

问题

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

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

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

enum class MyHandle : uint32_t { Null = 0; };


void addFunction(std::function<void(MyHandle)>&& fn) {
  mFunctions.push_back(fn);
}

我该如何实现这一目标?

英文:

I have a list of functions stored in a vector:

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:

enum class MyHandle : uint32_t { Null = 0; };


void addFunction(std::function&lt;void(MyHandle)&gt; &amp;&amp;fn) {
  mFunctions.push_back(fn);
}

How can I achieve this?

答案1

得分: 6

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

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

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

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

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

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

这里是代码运行的示例

英文:

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

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

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:

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

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

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

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:

确定