首页 > 解决方案 > C++ lambda 作为模板函数中的 std::function

问题描述

假设我们有我的代码的这个简化版本:

template<typename R>
R Context::executeTransient(std::function<R(VkCommandBuffer)> const &commands) {
    ...
    R result = commands(commandBuffer);
    ...
    return result;
}

我试图将 lambda 函数作为参数传递给该函数Context::executeTransient(),但只有当我将 lambda 显式分配给特定std::function类型时它才有效。这有效:

std::function<int(VkCommandBuffer)> f = [](VkCommandBuffer commandBuffer) {
    printf("Test execution");
    return 1;
};
context.executeTransient(f);

上面的例子有效,但由于美学原因,我想实现下面的例子,不知道这是否可能:

context.executeTransient([](VkCommandBuffer commandBuffer) {
    printf("Test execution");
    return 1;
});

我唯一的要求是Context::executeTransient()应该接受具有模板化返回类型的 lambda 和函数以及具有某些特定类型的输入参数,例如VkCommandBuffer.

标签: c++templateslambdatemplate-argument-deduction

解决方案


简单如下呢?

template <typename F>
auto Context::executeTransient (F const & commands) {
    ...
    auto result = commands(commandBuffer);
    ...
    return result;
}

这样,您的方法同时接受标准函数和 lambdas(不将它们转换为标准函数,从性能的角度来看(据我所知)这是更可取的),并且返回类型是从使用 ( auto) 推导出来的。

在你需要知道R方法里面的类型,你可以decltype()申请result

     auto result = commands(commandBuffer);

     using R = decltype(result);

如果您需要知道R类型作为方法的模板参数,它会有点复杂,因为涉及std::declval()并且不幸的是,添加了冗余

template <typename F,
          typename R = decltype(std::declval<F const &>()(commandBuffer))>
R Context::executeTransient (F const & commands) {
    ...
    R result = commands(commandBuffer);
    ...
    return result;
}

推荐阅读