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