基本上我想做的是制作一个函数模板,它接受任何 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/