Is it possible to pass a lambda function as a function pointer? If so, I must be doing something incorrectly because I am getting a compile error.
Consider the follo
Lambda expressions, even captured ones, can be handled as a function pointer (pointer to member function).
It is tricky because an lambda expression is not a simple function. It is actually an object with an operator().
When you are creative, you can use this! Think of an "function" class in style of std::function. If you save the object you also can use the function pointer.
To use the function pointer, you can use the following:
int first = 5;
auto lambda = [=](int x, int z) {
return x + z + first;
};
int(decltype(lambda)::*ptr)(int, int)const = &decltype(lambda)::operator();
std::cout << "test = " << (lambda.*ptr)(2, 3) << std::endl;
To build a class that can start working like a "std::function", first you need a class/struct than can store object and function pointer. Also you need an operator() to execute it:
// OT => Object Type
// RT => Return Type
// A ... => Arguments
template<typename OT, typename RT, typename ... A>
struct lambda_expression {
OT _object;
RT(OT::*_function)(A...)const;
lambda_expression(const OT & object)
: _object(object), _function(&decltype(_object)::operator()) {}
RT operator() (A ... args) const {
return (_object.*_function)(args...);
}
};
With this you can now run captured, non-captured lambdas, just like you are using the original:
auto capture_lambda() {
int first = 5;
auto lambda = [=](int x, int z) {
return x + z + first;
};
return lambda_expression<decltype(lambda), int, int, int>(lambda);
}
auto noncapture_lambda() {
auto lambda = [](int x, int z) {
return x + z;
};
return lambda_expression<decltype(lambda), int, int, int>(lambda);
}
void refcapture_lambda() {
int test;
auto lambda = [&](int x, int z) {
test = x + z;
};
lambda_expression<decltype(lambda), void, int, int>f(lambda);
f(2, 3);
std::cout << "test value = " << test << std::endl;
}
int main(int argc, char **argv) {
auto f_capture = capture_lambda();
auto f_noncapture = noncapture_lambda();
std::cout << "main test = " << f_capture(2, 3) << std::endl;
std::cout << "main test = " << f_noncapture(2, 3) << std::endl;
refcapture_lambda();
system("PAUSE");
return 0;
}
This code works with VS2015
Update 04.07.17:
template <typename CT, typename ... A> struct function
: public function<decltype(&CT::operator())(A...)> {};
template <typename C> struct function<C> {
private:
C mObject;
public:
function(const C & obj)
: mObject(obj) {}
template<typename... Args> typename
std::result_of<C(Args...)>::type operator()(Args... a) {
return this->mObject.operator()(a...);
}
template<typename... Args> typename
std::result_of<const C(Args...)>::type operator()(Args... a) const {
return this->mObject.operator()(a...);
}
};
namespace make {
template<typename C> auto function(const C & obj) {
return ::function<C>(obj);
}
}
int main(int argc, char ** argv) {
auto func = make::function([](int y, int x) { return x*y; });
std::cout << func(2, 4) << std::endl;
system("PAUSE");
return 0;
}
A simular answer but i made it so you don't have to specify the type of returned pointer (note that the generic version requires C++20):
#include <iostream>
template<typename Function>
struct function_traits;
template <typename Ret, typename... Args>
struct function_traits<Ret(Args...)> {
typedef Ret(*ptr)(Args...);
};
template <typename Ret, typename... Args>
struct function_traits<Ret(*const)(Args...)> : function_traits<Ret(Args...)> {};
template <typename Cls, typename Ret, typename... Args>
struct function_traits<Ret(Cls::*)(Args...) const> : function_traits<Ret(Args...)> {};
using voidfun = void(*)();
template <typename F>
voidfun lambda_to_void_function(F lambda) {
static auto lambda_copy = lambda;
return []() {
lambda_copy();
};
}
// requires C++20
template <typename F>
auto lambda_to_pointer(F lambda) -> typename function_traits<decltype(&F::operator())>::ptr {
static auto lambda_copy = lambda;
return []<typename... Args>(Args... args) {
return lambda_copy(args...);
};
}
int main() {
int num;
void(*foo)() = lambda_to_void_function([&num]() {
num = 1234;
});
foo();
std::cout << num << std::endl; // 1234
int(*bar)(int) = lambda_to_pointer([&](int a) -> int {
num = a;
return a;
});
std::cout << bar(4321) << std::endl; // 4321
std::cout << num << std::endl; // 4321
}
As it was mentioned by the others you can substitute Lambda function instead of function pointer. I am using this method in my C++ interface to F77 ODE solver RKSUITE.
//C interface to Fortran subroutine UT
extern "C" void UT(void(*)(double*,double*,double*),double*,double*,double*,
double*,double*,double*,int*);
// C++ wrapper which calls extern "C" void UT routine
static void rk_ut(void(*)(double*,double*,double*),double*,double*,double*,
double*,double*,double*,int*);
// Call of rk_ut with lambda passed instead of function pointer to derivative
// routine
mathlib::RungeKuttaSolver::rk_ut([](double* T,double* Y,double* YP)->void{YP[0]=Y[1]; YP[1]= -Y[0];}, TWANT,T,Y,YP,YMAX,WORK,UFLAG);
Not a direct answer, but a slight variation to use the "functor" template pattern to hide away the specifics of the lambda type and keeps the code nice and simple.
I was not sure how you wanted to use the decide class so I had to extend the class with a function that uses it. See full example here: https://godbolt.org/z/jtByqE
The basic form of your class might look like this:
template <typename Functor>
class Decide
{
public:
Decide(Functor dec) : _dec{dec} {}
private:
Functor _dec;
};
Where you pass the type of the function in as part of the class type used like:
auto decide_fc = [](int x){ return x > 3; };
Decide<decltype(decide_fc)> greaterThanThree{decide_fc};
Again, I was not sure why you are capturing x
it made more sense (to me) to have a parameter that you pass in to the lambda) so you can use like:
int result = _dec(5); // or whatever value
See the link for a complete example
Capturing lambdas cannot be converted to function pointers, as this answer pointed out.
However, it is often quite a pain to supply a function pointer to an API that only accepts one. The most often cited method to do so is to provide a function and call a static object with it.
static Callable callable;
static bool wrapper()
{
return callable();
}
This is tedious. We take this idea further and automate the process of creating wrapper
and make life much easier.
#include<type_traits>
#include<utility>
template<typename Callable>
union storage
{
storage() {}
std::decay_t<Callable> callable;
};
template<int, typename Callable, typename Ret, typename... Args>
auto fnptr_(Callable&& c, Ret (*)(Args...))
{
static bool used = false;
static storage<Callable> s;
using type = decltype(s.callable);
if(used)
s.callable.~type();
new (&s.callable) type(std::forward<Callable>(c));
used = true;
return [](Args... args) -> Ret {
return Ret(s.callable(std::forward<Args>(args)...));
};
}
template<typename Fn, int N = 0, typename Callable>
Fn* fnptr(Callable&& c)
{
return fnptr_<N>(std::forward<Callable>(c), (Fn*)nullptr);
}
And use it as
void foo(void (*fn)())
{
fn();
}
int main()
{
int i = 42;
auto fn = fnptr<void()>([i]{std::cout << i;});
foo(fn); // compiles!
}
Live
This is essentially declaring an anonymous function at each occurrence of fnptr
.
Note that invocations of fnptr
overwrite the previously written callable
given callables of the same type. We remedy this, to a certain degree, with the int
parameter N
.
std::function<void()> func1, func2;
auto fn1 = fnptr<void(), 1>(func1);
auto fn2 = fnptr<void(), 2>(func2); // different function
A shortcut for using a lambda with as a C function pointer is this:
"auto fun = +[](){}"
Using Curl as exmample (curl debug info)
auto callback = +[](CURL* handle, curl_infotype type, char* data, size_t size, void*){ //add code here :-) };
curl_easy_setopt(curlHande, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curlHande,CURLOPT_DEBUGFUNCTION,callback);