C++ 如何在模板中推断 Callable 的类型(参数列表和返回值)

标签 c++ templates functional-programming variadic-templates variadic-functions

基本上我想做的是制作一个函数模板,它接受任何 Callable(函数类型/lambda/Functor)并返回一个 lambda-taking-the-similar-args-list 并返回原始返回的类型类型

#include <iostream>

int func(int a,float b) {
    return a+b;
}

struct callable {
    int operator() (int a, float b) {
        return a+b;
    }
};

template <typename RV, typename... Args>
auto getLambdaFromCallable(RV(&func)(Args...)) {
    auto l = [&](Args... args) -> RV {
        return func(args...);
    };

    return l;
}

int main() {
    auto f = getLambdaFromCallable(func);
    std::cout << f(1,2.f);
    std::cout << " " << typeid(f).name();

    auto f2 = getLambdaFromCallable(callable{}); // doesn't work
    callable{}(1,2); // works

    auto lambdaTest = [](int a, float b) -> int {
        return a+b;
    };
    auto f3 = getLambdaFromCallable(lambdaTest);
}

最佳答案

您可以将 getLambdaFromCallable 更改为:

template <typename F>
auto getLambdaFromFunction(const F& func) {
  auto l = [&](auto&&... args) 
    -> decltype(func(std::forward<decltype(args)>(args)...)) {
    return func(std::forward<decltype(args)>(args)...);
  };

  return l;
}

这背后的原因是,由于您无法获得详尽的参数列表,因此您可以调用一个函数对象(首先可能有多个重载),您不妨使用一个通用的 lambda 接受所有内容并转发它到可调用对象。


详细说明这是如何工作的:

  • auto&&... 部分在 lambda 的调用运算符上转换为模板参数列表。

  • F 被推断为您调用 getLambdaFromFunction 的任何内容(没有 const 和引用,但如果需要可以更改).

  • decltype(args) 只是为了使用 std::forward 而正确地转发左值和右值引用,参见 std::forward更多详情。

生成的 lambda 对象将如下所示:

template <typename F>
class generatedLambda
{
public:
  template <typename... Args>
  auto operator()(Args&&... args) -> decltype(func(std::forward<decltype(args)>(args)...))
  {
    return func(std::forward<decltype(args)>(args)...);
  }

private:
  F     func;
};

关于C++ 如何在模板中推断 Callable 的类型(参数列表和返回值),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47327100/

相关文章:

c++ - 在 Cap'n Proto RPC 服务器中定期运行函数

未引用类的 C++ 静态变量

scala - 修改列表中条件为真的元素

c++ - 您可以从 MS SQL Server 调用 C++ 应用程序吗?

c++ - 为什么下面的多线程代码会导致 SIGABRT ?

c++17 有效地将参数包参数与 std::array 元素相乘

Azure ARM 模板 : DocumentDB primaryMasterKey as OUTPUT

haskell - 通过替换变态来消除显式递归

functional-programming - 函数式、动态和面向方面的编程模式

c++ - R6030 CRT 未初始化