I was playing with C++ lambdas and their implicit conversion to function pointers. My starting example was using them as callback for the ftw function. This works as expecte
Hehe - quite an old question, but still...
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
// We dont try to outsmart the compiler...
template<typename T>
int ftw(const char *fpath, T callback) {
return callback(fpath);
}
int main()
{
vector<string> entries;
// ... now the @ftw can accept lambda
int ret = ftw("/etc", [&](const char *fpath) -> int {
entries.push_back(fpath);
return 0;
});
// ... and function object too
struct _ {
static int lambda(vector<string>& entries, const char* fpath) {
entries.push_back(fpath);
return 0;
}
};
ret = ftw("/tmp", bind(_::lambda, ref(entries), placeholders::_1));
for (auto entry : entries ) {
cout << entry << endl;
}
return ret;
}
Using locally global (static) method it can be done as followed
template <class F>
auto cify_no_args(F&& f) {
static F fn = std::forward<F>(f);
return [] {
return fn();
};
}
Suppose we have
void some_c_func(void (*callback)());
So the usage will be
some_c_func(cify_no_args([&] {
// code
}));
This works because each lambda has an unique signature so making it static is not a problem. Following is a generic wrapper with variadic number of arguments and any return type using the same method.
template <class F>
struct lambda_traits : lambda_traits<decltype(&F::operator())>
{ };
template <typename F, typename R, typename... Args>
struct lambda_traits<R(F::*)(Args...)> : lambda_traits<R(F::*)(Args...) const>
{ };
template <class F, class R, class... Args>
struct lambda_traits<R(F::*)(Args...) const> {
using pointer = typename std::add_pointer<R(Args...)>::type;
static pointer cify(F&& f) {
static F fn = std::forward<F>(f);
return [](Args... args) {
return fn(std::forward<Args>(args)...);
};
}
};
template <class F>
inline lambda_traits<F>::pointer cify(F&& f) {
return lambda_traits<F>::cify(std::forward<F>(f));
}
And similar usage
void some_c_func(int (*callback)(some_struct*, float));
some_c_func(cify([&](some_struct* s, float f) {
// making use of "s" and "f"
return 0;
}));