传递给模板函数时lambda自动衰减到函数指针

时间:2014-03-10 11:27:05

标签: c++ templates c++11 lambda function-pointers

有没有办法让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 具有任何签名衰减,所以我回到原点。

3 个答案:

答案 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;
}

尝试删除回调定义中的+,一切停止工作。