有没有办法让lambda衰减到指针,而没有明确地转换为正确的签名?这将整理一些代码:
template<typename T> T call(T(*func)()){ return func(); }
int ptr(){ return 0; }
int main(){
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; }));
auto ret3 = call([]{ return 0; }); //won't compile
}
很明显,只有当lambda衰减到指针时,对call
的调用才有效,但我猜测只有在选择了正确的函数重载/模板之后才会发生这种情况。不幸的是,我只能想到涉及模板的解决方案,以使lambda 具有任何签名衰减,所以我回到原点。
答案 0 :(得分:13)
您可以更改lambda以使用一元+
运算符:+[]{ return 0; }
这是有效的,因为一元加号可以应用于指针,并将触发隐式转换为函数指针。
答案 1 :(得分:1)
为什么你会不必要地将你自己限制在没有默认参数和没有捕获的lambdas的函数指针上,完全排除了大量的仿函数(例如std::function
),std::bind
的任何结果以及其他所有的结果合适的operator()
)?
最好只是扩大你的功能签名:
template <typename F>
auto call(F func) -> decltype(func()) {
return func();
}
int ptr() { return 0; }
int g(int i = 0) {return i;}
int main() {
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; })); //tedious, but works
auto ret3 = call([]{ return 0; }); //ok now.
auto ret4 = call(g); //ok now!
int i = 42;
auto ret5 = call([=]{return i;}); //works, too!
auto ret6 = call(std::bind(g, i)); //and so on...
}
答案 2 :(得分:0)
作为TL; DR; @Simple提案的实现,我编写了一个简单的测试,如下所示:
SCENARIO("decay_equiv", "")
{
auto callback = +[](struct mosquitto *, void *,
const struct mosquitto_message *)->void{};
typedef typename std::is_same<
typename std::decay<decltype(callback)>::type,
typename std::decay<void (*)(struct mosquitto *, void *, const struct mosquitto_message *)>::type
>::type s;
std::cout << s::value << std::endl;
}
尝试删除回调定义中的+
,一切停止工作。