问题
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.
回答1:
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.
回答2:
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...
}
回答3:
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.
来源:https://stackoverflow.com/questions/22298865/automatic-decay-of-lambda-to-function-pointer-when-passing-to-template-function