【问题标题】:C++ lambda as std::function in template functionC++ lambda 作为模板函数中的 std::function
【发布时间】:2021-06-30 01:03:37
【问题描述】:

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

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++ templates lambda template-argument-deduction


    【解决方案1】:

    简单如下呢?

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

    通过这种方式,您的方法同时接受标准函数和 lambda(不将它们转换为标准函数,从性能的角度来看(据我所知)这是可取的),并且返回类型是从使用 (@ 987654323@)。

    如果你需要知道方法里面的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;
    }
    

    【讨论】:

    • 如果我将实现放在标题中,第一个代码 sn-p 可以完美运行。如果commandBuffer 不是局部变量,第三个也可以工作。除了在标头中复制实现之外还有其他解决方法吗?
    • @batthomas - 建议:曾经 (ever) 将模板(类/结构、函数、方法)的实现放在标题中。不是绝对必要的,但通常可以避免很多麻烦。更多信息this answer
    猜你喜欢
    • 1970-01-01
    • 2020-05-06
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多