std::bind with variadic template function - c++

I'm trying to write a generic obj factory using variadic template to call constructors of various classes. code as follow:
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <unordered_map>
template<typename T>
class ObjFactory {
public:
typedef std::shared_ptr<T> ObjPtr;
typedef std::function<ObjPtr(void)> CreatorFunc;
public:
void registerCreator(const std::string &name, const CreatorFunc &creator)
{ m_dictCreator[name] = creator; }
ObjPtr getObj(const std::string &name) const
{
auto it = m_dictCreator.find(name);
return (it == m_dictCreator.end() ? nullptr : (it->second)());
}
private:
std::unordered_map<std::string, CreatorFunc> m_dictCreator;
};
using namespace std;
struct Base {
virtual ~Base() {}
virtual void greet() const
{ cout << "I am Base" << endl; }
};
struct Derived : Base {
Derived() : x(0), y(0) {}
Derived(int a, int b) : x(a), y(b) {}
int x, y;
virtual void greet() const
{ cout << "I am Derived x = " << x << " y = " << y << endl; }
};
template<typename T, typename... Args>
std::shared_ptr<T> create_obj(Args... args) // This OK
// std::shared_ptr<T> create_obj(Args&&... args) // WRONG
{ return std::make_shared<T>(std::forward<Args>(args)...); }
int main()
{
ObjFactory<Base> factory;
factory.registerCreator("default", create_obj<Derived>);
factory.registerCreator("withArgs", std::bind(create_obj<Derived, int, int>, 1, 2));
do {
auto pObj = factory.getObj("default1");
if (pObj) { pObj->greet(); }
} while (0);
do {
auto pObj = factory.getObj("withArgs");
if (pObj) { pObj->greet(); }
} while (0);
return 0;
}
In most examples, variadic arg always write like this "Args&&..." in function arg list. but this does not work with bind, compile error msg like this (clang-902.0.39.2)
error: no viable conversion from '__bind
(&)(int &&, int
&&), int, int>' to 'const ObjFactory::CreatorFunc' (aka 'const function ()>')
factory.registerCreator("withArgs", std::bind(create_obj, 1, 2));
After removing the "&&", it works OK
But I don't know why?

Universal references only work in a deduced context. They do not function as you expect when the template parameters are explicitly specified.
Given the function template
template <typename... Args>
void foo(Args&&... args) {}
And the call
int a = 1;
int b = 2;
foo(a, b);
Args will be deduced to be {int&, int&}. Reference collapsing is applied, and int& && gets collapsed to just int&. That means the types of the values in args are {int&, int&}.
If you call it with rvalues for arguments (i.e. foo(1, 2)) then Args will be deduced to be {int, int} and the types of the values in args become {int&&, int&&}.
That's the basics of universal references, so now let's look at what happens when you call
auto fn = std::bind(foo<int, int>, 1, 2);
fn();
Here, you've not allowed template argument deduction to take place so Args is {int, int} and foo is therefore expecting arguments of type {int&&, int&&}. The values 1, and 2 are copied into the bind object and passed to the callable as lvalues though. Rvalue references can't bind to lvalues, and so the call fails to compile.
The way to make this work correctly is to use a lambda instead of std::bind:
auto fn = []() { foo(1, 2); };
fn();
With a lambda, template argument deduction works as normal, and 1, and 2 remain rvalues. Everything works as expected and the universal references do their job because they're being used in a deduced context.

when using forwarding references you need to let argument being deduced otherwise you can't perfect forward them because you won't know the real type to use for them.
in your case you gave a type create_obj<Derived, int, int>
the function will be instantiated to std::shared_ptr<Derived> create_obj(int&&, int&&) and have no flexibility it will just be taking r-value int.
and you assigned the callable to a const CreatorFunc& and so the closure was const and your callable couldn't receive const arguments
replacing create_obj<Derived, int, int> by create_obj<Derived, const int&, const int&> which cause create_obj to be instantiated as std::shared_ptr<Derived> create_obj(const int&, const int&) will work in this case but would still not have the flexibility of forwarding references.
the real solution is to use lambda.

Related

How to assign c++ lambda into function pointer? [duplicate]

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 following example
using DecisionFn = bool(*)();
class Decide
{
public:
Decide(DecisionFn dec) : _dec{dec} {}
private:
DecisionFn _dec;
};
int main()
{
int x = 5;
Decide greaterThanThree{ [x](){ return x > 3; } };
return 0;
}
When I try to compile this, I get the following compilation error:
In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9: note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5: note: Decide::Decide(DecisionFn)
9:5: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7: note: constexpr Decide::Decide(const Decide&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7: note: constexpr Decide::Decide(Decide&&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'
That's one heck of an error message to digest, but I think what I'm getting out of it is that the lambda cannot be treated as a constexpr so therefore I cannot pass it as a function pointer? I've tried making x constexpr as well, but that doesn't seem to help.
A lambda can only be converted to a function pointer if it does not capture, from the draft C++11 standard section 5.1.2 [expr.prim.lambda] says (emphasis mine):
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
Note, cppreference also covers this in their section on Lambda functions.
So the following alternatives would work:
typedef bool(*DecisionFn)(int);
Decide greaterThanThree{ []( int x ){ return x > 3; } };
and so would this:
typedef bool(*DecisionFn)();
Decide greaterThanThree{ [](){ return true ; } };
and as 5gon12eder points out, you can also use std::function, but note that std::function is heavy weight, so it is not a cost-less trade-off.
Shafik Yaghmour's answer correctly explains why the lambda cannot be passed as a function pointer if it has a capture. I'd like to show two simple fixes for the problem.
Use std::function instead of raw function pointers.
This is a very clean solution. Note however that it includes some additional overhead for the type erasure (probably a virtual function call).
#include <functional>
#include <utility>
struct Decide
{
using DecisionFn = std::function<bool()>;
Decide(DecisionFn dec) : dec_ {std::move(dec)} {}
DecisionFn dec_;
};
int
main()
{
int x = 5;
Decide greaterThanThree { [x](){ return x > 3; } };
}
Use a lambda expression that doesn't capture anything.
Since your predicate is really just a boolean constant, the following would quickly work around the current issue. See this answer for a good explanation why and how this is working.
// Your 'Decide' class as in your post.
int
main()
{
int x = 5;
Decide greaterThanThree {
(x > 3) ? [](){ return true; } : [](){ return false; }
};
}
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;
}
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
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
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);
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
}
Here is another variation of the solution. C++14 (can be turned into C++11) Supports return values, non-copyable and mutable lambdas. If mutable lambdas not needed, can be even shorter by removing specialization matching non-const version and embedding impl_impl.
For those who wonder, it works because each lambda is unique (is distinct class) and thus invocation of to_f generates unique for this lambda static and corresponding C-style function which can access it.
template <class L, class R, class... Args> static auto impl_impl(L l) {
static_assert(!std::is_same<L, std::function<R(Args...)>>::value,
"Only lambdas are supported, it is unsafe to use "
"std::function or other non-lambda callables");
static L lambda_s = std::move(l);
return +[](Args... args) -> R { return lambda_s(args...); };
}
template <class L>
struct to_f_impl : public to_f_impl<decltype(&L::operator())> {};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...) const> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...)> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class L> auto to_f(L l) { return to_f_impl<L>::impl(std::move(l)); }
Note, this also tend to work for other callable objects like std::function but it would be better if it didn't work because unlike lambdas, std::function like objects do not generate unique type so inner template and its inner static will be reused for/shared by all functions with same signature, which most probably is not what we want from it. I've specifically disallowed std::function but there exist more which I don't know how to disallow in generic way.
While the template approach is clever for various reasons, it is important to remember the lifecycle of the lambda and the captured variables. If any form of a lambda pointer is is going to be used and the lambda is not a downward continuation, then only a copying [=] lambda should used. I.e., even then, capturing a pointer to a variable on the stack is UNSAFE if the lifetime of those captured pointers (stack unwind) is shorter than the lifetime of the lambda.
A simpler solution for capturing a lambda as a pointer is:
auto pLamdba = new std::function<...fn-sig...>([=](...fn-sig...){...});
e.g., new std::function<void()>([=]() -> void {...}
Just remember to later delete pLamdba so ensure that you don't leak the lambda memory.
Secret to realize here is that lambdas can capture lambdas (ask yourself how that works) and also that in order for std::function to work generically the lambda implementation needs to contain sufficient internal information to provide access to the size of the lambda (and captured) data (which is why the delete should work [running destructors of captured types]).
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);

C++ lambda type conversion? [duplicate]

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 following example
using DecisionFn = bool(*)();
class Decide
{
public:
Decide(DecisionFn dec) : _dec{dec} {}
private:
DecisionFn _dec;
};
int main()
{
int x = 5;
Decide greaterThanThree{ [x](){ return x > 3; } };
return 0;
}
When I try to compile this, I get the following compilation error:
In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9: note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5: note: Decide::Decide(DecisionFn)
9:5: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7: note: constexpr Decide::Decide(const Decide&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7: note: constexpr Decide::Decide(Decide&&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'
That's one heck of an error message to digest, but I think what I'm getting out of it is that the lambda cannot be treated as a constexpr so therefore I cannot pass it as a function pointer? I've tried making x constexpr as well, but that doesn't seem to help.
A lambda can only be converted to a function pointer if it does not capture, from the draft C++11 standard section 5.1.2 [expr.prim.lambda] says (emphasis mine):
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
Note, cppreference also covers this in their section on Lambda functions.
So the following alternatives would work:
typedef bool(*DecisionFn)(int);
Decide greaterThanThree{ []( int x ){ return x > 3; } };
and so would this:
typedef bool(*DecisionFn)();
Decide greaterThanThree{ [](){ return true ; } };
and as 5gon12eder points out, you can also use std::function, but note that std::function is heavy weight, so it is not a cost-less trade-off.
Shafik Yaghmour's answer correctly explains why the lambda cannot be passed as a function pointer if it has a capture. I'd like to show two simple fixes for the problem.
Use std::function instead of raw function pointers.
This is a very clean solution. Note however that it includes some additional overhead for the type erasure (probably a virtual function call).
#include <functional>
#include <utility>
struct Decide
{
using DecisionFn = std::function<bool()>;
Decide(DecisionFn dec) : dec_ {std::move(dec)} {}
DecisionFn dec_;
};
int
main()
{
int x = 5;
Decide greaterThanThree { [x](){ return x > 3; } };
}
Use a lambda expression that doesn't capture anything.
Since your predicate is really just a boolean constant, the following would quickly work around the current issue. See this answer for a good explanation why and how this is working.
// Your 'Decide' class as in your post.
int
main()
{
int x = 5;
Decide greaterThanThree {
(x > 3) ? [](){ return true; } : [](){ return false; }
};
}
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;
}
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
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
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);
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
}
Here is another variation of the solution. C++14 (can be turned into C++11) Supports return values, non-copyable and mutable lambdas. If mutable lambdas not needed, can be even shorter by removing specialization matching non-const version and embedding impl_impl.
For those who wonder, it works because each lambda is unique (is distinct class) and thus invocation of to_f generates unique for this lambda static and corresponding C-style function which can access it.
template <class L, class R, class... Args> static auto impl_impl(L l) {
static_assert(!std::is_same<L, std::function<R(Args...)>>::value,
"Only lambdas are supported, it is unsafe to use "
"std::function or other non-lambda callables");
static L lambda_s = std::move(l);
return +[](Args... args) -> R { return lambda_s(args...); };
}
template <class L>
struct to_f_impl : public to_f_impl<decltype(&L::operator())> {};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...) const> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...)> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class L> auto to_f(L l) { return to_f_impl<L>::impl(std::move(l)); }
Note, this also tend to work for other callable objects like std::function but it would be better if it didn't work because unlike lambdas, std::function like objects do not generate unique type so inner template and its inner static will be reused for/shared by all functions with same signature, which most probably is not what we want from it. I've specifically disallowed std::function but there exist more which I don't know how to disallow in generic way.
While the template approach is clever for various reasons, it is important to remember the lifecycle of the lambda and the captured variables. If any form of a lambda pointer is is going to be used and the lambda is not a downward continuation, then only a copying [=] lambda should used. I.e., even then, capturing a pointer to a variable on the stack is UNSAFE if the lifetime of those captured pointers (stack unwind) is shorter than the lifetime of the lambda.
A simpler solution for capturing a lambda as a pointer is:
auto pLamdba = new std::function<...fn-sig...>([=](...fn-sig...){...});
e.g., new std::function<void()>([=]() -> void {...}
Just remember to later delete pLamdba so ensure that you don't leak the lambda memory.
Secret to realize here is that lambdas can capture lambdas (ask yourself how that works) and also that in order for std::function to work generically the lambda implementation needs to contain sufficient internal information to provide access to the size of the lambda (and captured) data (which is why the delete should work [running destructors of captured types]).
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);

callback on object method C++ [duplicate]

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 following example
using DecisionFn = bool(*)();
class Decide
{
public:
Decide(DecisionFn dec) : _dec{dec} {}
private:
DecisionFn _dec;
};
int main()
{
int x = 5;
Decide greaterThanThree{ [x](){ return x > 3; } };
return 0;
}
When I try to compile this, I get the following compilation error:
In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9: note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5: note: Decide::Decide(DecisionFn)
9:5: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7: note: constexpr Decide::Decide(const Decide&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7: note: constexpr Decide::Decide(Decide&&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'
That's one heck of an error message to digest, but I think what I'm getting out of it is that the lambda cannot be treated as a constexpr so therefore I cannot pass it as a function pointer? I've tried making x constexpr as well, but that doesn't seem to help.
A lambda can only be converted to a function pointer if it does not capture, from the draft C++11 standard section 5.1.2 [expr.prim.lambda] says (emphasis mine):
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
Note, cppreference also covers this in their section on Lambda functions.
So the following alternatives would work:
typedef bool(*DecisionFn)(int);
Decide greaterThanThree{ []( int x ){ return x > 3; } };
and so would this:
typedef bool(*DecisionFn)();
Decide greaterThanThree{ [](){ return true ; } };
and as 5gon12eder points out, you can also use std::function, but note that std::function is heavy weight, so it is not a cost-less trade-off.
Shafik Yaghmour's answer correctly explains why the lambda cannot be passed as a function pointer if it has a capture. I'd like to show two simple fixes for the problem.
Use std::function instead of raw function pointers.
This is a very clean solution. Note however that it includes some additional overhead for the type erasure (probably a virtual function call).
#include <functional>
#include <utility>
struct Decide
{
using DecisionFn = std::function<bool()>;
Decide(DecisionFn dec) : dec_ {std::move(dec)} {}
DecisionFn dec_;
};
int
main()
{
int x = 5;
Decide greaterThanThree { [x](){ return x > 3; } };
}
Use a lambda expression that doesn't capture anything.
Since your predicate is really just a boolean constant, the following would quickly work around the current issue. See this answer for a good explanation why and how this is working.
// Your 'Decide' class as in your post.
int
main()
{
int x = 5;
Decide greaterThanThree {
(x > 3) ? [](){ return true; } : [](){ return false; }
};
}
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;
}
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
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
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);
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
}
Here is another variation of the solution. C++14 (can be turned into C++11) Supports return values, non-copyable and mutable lambdas. If mutable lambdas not needed, can be even shorter by removing specialization matching non-const version and embedding impl_impl.
For those who wonder, it works because each lambda is unique (is distinct class) and thus invocation of to_f generates unique for this lambda static and corresponding C-style function which can access it.
template <class L, class R, class... Args> static auto impl_impl(L l) {
static_assert(!std::is_same<L, std::function<R(Args...)>>::value,
"Only lambdas are supported, it is unsafe to use "
"std::function or other non-lambda callables");
static L lambda_s = std::move(l);
return +[](Args... args) -> R { return lambda_s(args...); };
}
template <class L>
struct to_f_impl : public to_f_impl<decltype(&L::operator())> {};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...) const> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...)> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class L> auto to_f(L l) { return to_f_impl<L>::impl(std::move(l)); }
Note, this also tend to work for other callable objects like std::function but it would be better if it didn't work because unlike lambdas, std::function like objects do not generate unique type so inner template and its inner static will be reused for/shared by all functions with same signature, which most probably is not what we want from it. I've specifically disallowed std::function but there exist more which I don't know how to disallow in generic way.
While the template approach is clever for various reasons, it is important to remember the lifecycle of the lambda and the captured variables. If any form of a lambda pointer is is going to be used and the lambda is not a downward continuation, then only a copying [=] lambda should used. I.e., even then, capturing a pointer to a variable on the stack is UNSAFE if the lifetime of those captured pointers (stack unwind) is shorter than the lifetime of the lambda.
A simpler solution for capturing a lambda as a pointer is:
auto pLamdba = new std::function<...fn-sig...>([=](...fn-sig...){...});
e.g., new std::function<void()>([=]() -> void {...}
Just remember to later delete pLamdba so ensure that you don't leak the lambda memory.
Secret to realize here is that lambdas can capture lambdas (ask yourself how that works) and also that in order for std::function to work generically the lambda implementation needs to contain sufficient internal information to provide access to the size of the lambda (and captured) data (which is why the delete should work [running destructors of captured types]).
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);

Semantically, are lambdas real functions in C++? How can I point to a lambda expression to prove it? [duplicate]

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 following example
using DecisionFn = bool(*)();
class Decide
{
public:
Decide(DecisionFn dec) : _dec{dec} {}
private:
DecisionFn _dec;
};
int main()
{
int x = 5;
Decide greaterThanThree{ [x](){ return x > 3; } };
return 0;
}
When I try to compile this, I get the following compilation error:
In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9: note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5: note: Decide::Decide(DecisionFn)
9:5: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7: note: constexpr Decide::Decide(const Decide&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7: note: constexpr Decide::Decide(Decide&&)
6:7: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'
That's one heck of an error message to digest, but I think what I'm getting out of it is that the lambda cannot be treated as a constexpr so therefore I cannot pass it as a function pointer? I've tried making x constexpr as well, but that doesn't seem to help.
A lambda can only be converted to a function pointer if it does not capture, from the draft C++11 standard section 5.1.2 [expr.prim.lambda] says (emphasis mine):
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
Note, cppreference also covers this in their section on Lambda functions.
So the following alternatives would work:
typedef bool(*DecisionFn)(int);
Decide greaterThanThree{ []( int x ){ return x > 3; } };
and so would this:
typedef bool(*DecisionFn)();
Decide greaterThanThree{ [](){ return true ; } };
and as 5gon12eder points out, you can also use std::function, but note that std::function is heavy weight, so it is not a cost-less trade-off.
Shafik Yaghmour's answer correctly explains why the lambda cannot be passed as a function pointer if it has a capture. I'd like to show two simple fixes for the problem.
Use std::function instead of raw function pointers.
This is a very clean solution. Note however that it includes some additional overhead for the type erasure (probably a virtual function call).
#include <functional>
#include <utility>
struct Decide
{
using DecisionFn = std::function<bool()>;
Decide(DecisionFn dec) : dec_ {std::move(dec)} {}
DecisionFn dec_;
};
int
main()
{
int x = 5;
Decide greaterThanThree { [x](){ return x > 3; } };
}
Use a lambda expression that doesn't capture anything.
Since your predicate is really just a boolean constant, the following would quickly work around the current issue. See this answer for a good explanation why and how this is working.
// Your 'Decide' class as in your post.
int
main()
{
int x = 5;
Decide greaterThanThree {
(x > 3) ? [](){ return true; } : [](){ return false; }
};
}
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;
}
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
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
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);
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
}
Here is another variation of the solution. C++14 (can be turned into C++11) Supports return values, non-copyable and mutable lambdas. If mutable lambdas not needed, can be even shorter by removing specialization matching non-const version and embedding impl_impl.
For those who wonder, it works because each lambda is unique (is distinct class) and thus invocation of to_f generates unique for this lambda static and corresponding C-style function which can access it.
template <class L, class R, class... Args> static auto impl_impl(L l) {
static_assert(!std::is_same<L, std::function<R(Args...)>>::value,
"Only lambdas are supported, it is unsafe to use "
"std::function or other non-lambda callables");
static L lambda_s = std::move(l);
return +[](Args... args) -> R { return lambda_s(args...); };
}
template <class L>
struct to_f_impl : public to_f_impl<decltype(&L::operator())> {};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...) const> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class ClassType, class R, class... Args>
struct to_f_impl<R (ClassType::*)(Args...)> {
template <class L> static auto impl(L l) {
return impl_impl<L, R, Args...>(std::move(l));
}
};
template <class L> auto to_f(L l) { return to_f_impl<L>::impl(std::move(l)); }
Note, this also tend to work for other callable objects like std::function but it would be better if it didn't work because unlike lambdas, std::function like objects do not generate unique type so inner template and its inner static will be reused for/shared by all functions with same signature, which most probably is not what we want from it. I've specifically disallowed std::function but there exist more which I don't know how to disallow in generic way.
While the template approach is clever for various reasons, it is important to remember the lifecycle of the lambda and the captured variables. If any form of a lambda pointer is is going to be used and the lambda is not a downward continuation, then only a copying [=] lambda should used. I.e., even then, capturing a pointer to a variable on the stack is UNSAFE if the lifetime of those captured pointers (stack unwind) is shorter than the lifetime of the lambda.
A simpler solution for capturing a lambda as a pointer is:
auto pLamdba = new std::function<...fn-sig...>([=](...fn-sig...){...});
e.g., new std::function<void()>([=]() -> void {...}
Just remember to later delete pLamdba so ensure that you don't leak the lambda memory.
Secret to realize here is that lambdas can capture lambdas (ask yourself how that works) and also that in order for std::function to work generically the lambda implementation needs to contain sufficient internal information to provide access to the size of the lambda (and captured) data (which is why the delete should work [running destructors of captured types]).
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);

Given the following, what type is "function"?

Given the following, what type is "function"?
#include <functional>
#include <vector>
template<class T>
class Foo
{
public:
template<typename P, typename Q, typename R, typename... Args>
void Attach(P (Q::*f)(Args...), R p)
{
auto function = [p, f](Args... args)
{
(*p.*f)(args...);
};
Listeners.push_back(function);
}
private:
std::vector<std::function<T>> Listeners;
};
class Bar
{
public:
int Handler(int x, int y, int z)
{
return 0;
}
};
int main(void)
{
auto foo = Foo<int(int, int, int)>();
auto bar = Bar();
foo.Attach(&Bar::Handler, &bar);
}
For some context I'm attempting to make a lambda that calls a method on an instance, storing that lambda into a collection. My push_back fails to compile, with the following error:
xrefwrap(283): error C2440: 'return' : cannot convert from 'void' to
'int'
I was originally using std::bind to make a std::function that I could store. Apparently I may be able to do it with a lambda (and variadic templates, so I don't need one template per arity) but so far it's defeating me.
When you have constructed Foo, the explicit template argument supplied is auto foo = Foo<int(int, int, int)>();,
int main(void)
{
auto foo = Foo<int(int, int, int)>(); //<<<< Here is the template arguments when constructing Foo
auto bar = Bar();
foo.Attach(&Bar::Handler, &bar);
}
where as when you are registering the listener the function signatures return type is void
auto function = [p, f](Args... args)
{
(*p.*f)(args...);
};
Resolution
So either you
change the explicit template argument of Foo, auto foo = Foo<void(int, int, int)>(); to return void to match your listener callback.
or ensure that your listener function returns an integer. return (*p.*f)(args...);
Note May be you intended to return a status code from the listener but you might have missed? So the second resolution point looks to me an obvious plausible issue