문제

Is there a way to make a lambda decay to a pointer, without explicitly casting to the right signature? This would tidy some code:

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
}

It's evident that a call to call works only if the lambda decays to a pointer, but I'm guessing that that can happen only after the right function overload/template is chosen. Unfortunately I can only think of solutions that involve templates to make a lambda with any signature decay, so I'm back to square one.

도움이 되었습니까?

해결책

You can change your lambda to use the unary + operator: +[]{ return 0; }

This works because unary plus can be applied to pointers, and will trigger the implicit conversion to function pointer.

다른 팁

Why would you unnecessarily constrain yourself to function pointers without defaulted arguments and lambdas without captures, completely ruling out the huge family of functors (e.g. std::function, any results of std::bind and everything else that has a suitable operator())?

Better just broaden your function signature:

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...
}

As a TL;DR; implementation of the @Simple proposal, I have write a simple test as follow:

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

Try it removing the + in the callback definition and everything stop to work.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top