基本上我想做的是制作一个函数模板,它接受任何 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 ,而 ojit_code 又可以正确转发左值和右值引用,有关更多详细信息,请参阅 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/

    10-09 06:34
    查看更多