如何最好地定义模板函数@
以匹配lambda&#39签名?
我不想定义一个捕获整个函数类型的通用模板参数,
因为我想使用传入函数的参数类型applyFunc
。
E
编译失败:
#include <functional>
template<class E>
int applyFunc(std::function<int(E)> f) {
return f(E{});
}
int main()
{
auto asLambda = [](int d) -> int { return d+d; };
std::function<int(int)> asFunc = asLambda;
applyFunc(asLambda); //this doesn't :(
applyFunc(asFunc); //this works
}
答案 0 :(得分:1)
如何最好地定义模板函数applyFunc以匹配lambda的签名?
只要您接受仅使用非捕获lambdas(就像在示例代码中所做的那样),就可以利用它们衰减到函数指针的事实。
作为一个最小的工作示例:
template<class E>
int applyFunc(int(*f)(E)) {
return f(E{});
}
int main() {
auto asLambda = [](int d) -> int { return d+d; };
applyFunc(+asLambda);
}
如果你想使用捕获lambdas,你可以以某种方式提取类型E
如果你接受以下内容:
F
而不是std::function
然后,您可以直接查看您的lambda的operator()
它遵循一个最小的工作示例:
template<typename F>
struct GetFrom {
template<typename R, typename E>
static E typeE(R(F::*)(E) const);
// required for mutable lambdas
template<typename R, typename E>
static E typeE(R(F::*)(E));
};
template<class F>
int applyFunc(F f) {
using E = decltype(GetFrom<F>::typeE(&F::operator()));
return f(E{});
}
int main() {
int i = 0;
applyFunc([i](int d) mutable -> int { return d+d; });
applyFunc([i](int d) -> int { return d+d; });
}
如果需要,您可以轻松地将其扩展为多个参数。使用std::tuple
作为返回类型并从中获取第i种类型。
最后,如果你想使用捕获lambdas并因任何原因将它们分配给std::function
,请注意E
不能自动推断,因此你必须明确指定它(如@cpplearner对问题的评论:
applyFunc<int>([](int d) { return d+d; })
修改强>
GetFrom
也可以直接在SFINAE表达式中使用,如评论中所要求的
作为一个最小的工作示例:
#include<type_traits>
template<typename F>
struct GetFrom {
template<typename R, typename E>
static E typeE(R(F::*)(E) const);
// required for mutable lambdas
template<typename R, typename E>
static E typeE(R(F::*)(E));
};
template<class F, typename E = decltype(GetFrom<F>::typeE(&F::operator()))>
std::enable_if_t<std::is_same<E, int>::value, E>
applyFunc(F f) {
return f(E{});
}
template<class F, typename E = decltype(GetFrom<F>::typeE(&F::operator()))>
std::enable_if_t<std::is_same<E, double>::value, E>
applyFunc(F f) {
return f(E{});
}
int main() {
int i = 0;
applyFunc([i](int d) mutable -> int { return d+d; });
applyFunc([i](double d) -> int { return d+d; });
// this won't compile, as expected
// applyFunc([i](char d) -> int { return d+d; });
}