By CoryKramer


2015-02-26 15:45:23 8 Comments

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 const as well, but that doesn't seem to help.

7 comments

@Noxxer 2017-01-08 01:17:26

I know this a little bit old..

But i wanted to add:

Lambda expression (even captured ones) can be handled as a funtion 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" i will just do short example. 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, noncaptured 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 Hope it helps : )

Greets!

Edit: removed needles template FP, removed function pointer parameter, renamed to lambda_expression

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

@barney 2017-06-03 08:16:23

Wow That's amazing! So we just could use lambda's class inner pointers (to member function operator() ) to invoke stored lambdas in a wrapper class!! AMAZING!! Why do we ever need the std::function then? And is it possible to make lambda_expression<decltype(lambda), int, int, int> to automatically deduce/ these "int" parameters directly from the passed lambda itself?

@Noxxer 2017-07-04 20:34:08

I've added a short version of my own code. this should be working with a simple auto f = make::function(lambda); But i'm quite shure you will find plenty of situation my code will not work. std::function is way more well constructed than this and should be the go to when you are working. This here is for education and personal use.

@barney 2017-07-11 12:28:13

very curious! Interestingly, how does it parse? Is the expression "C(Args...)" constructor taking template parameter pack? Why then its resulting type is valid return for "operator()" as far as I know constructors don't return any values so how does this "result_of" deduces the operator()'s return type from the C type itself?))

@Noxxer 2017-07-17 16:39:40

I've edit now with a "full" example. I think i don't quite get the question right now. sry! I tried to code std::result_of but the code involves many 1000 lines in the std library. I gave up about this. I really can't tell you how it works by now. I can only say: When you call operator() with some parameters the code above will look up: Is there a solution for the expression and what is the result type? No constructor needed. So the Parameter you will pass to operator() will define which overload is the one you're trying to use. This isn't needed for lambda but for overloaded "normal" classes.

@barney 2017-07-17 16:43:17

Oh, I see, it uses std::result_of that is a new bit of STL magic ) I tried to understand it looks like its implementation uses some ideas of type deduction from your prev. implementation deducting somehow the RetType from T. Anyway you did very cool and elegant solution Appreciate it :)

@Remy Lebeau 2017-07-28 03:48:49

This solution involves calling the lambda via an operator() implementation, so if I'm reading it right I don't think it would work to call the lambda using a C-style function pointer, would it? That is what the the original question asked for.

@Noxxer 2017-07-29 08:33:50

I disagree. When somebody asks "how can you use a C-Sytel Function Pointer for Object method" you would answer it with an example of a "Object-Method" Functionpointer. Since lambda is actually an Object, it was the very first thing i did in my answer. Second part was how to create your own "functionpointer feel-a-like" class and third to what it has evolved after some questions in the comments. I think that might help some people and also explains a lot how lambdas work. : )

@Passer By 2017-08-01 12:47:50

You claimed that lambdas can be handled as function pointers, which you didn't do. You created another object to hold a lambda, which does nothing, you could've just used the original lambda.

@Noxxer 2017-08-03 17:41:46

A "member-function" pointer is a function pointer. : ) That "you need the object for it" was allways up in the text above. First code up there shows how it works. The rest is a bit more future possibilities with it. ; )

@Alexander 2017-10-25 18:22:23

Why is it necessary to store _object as a member of lambda_expression? Can't the (_object.*_function) part be moved from operator () to the constructor, and used to get a raw function pointer?

@Noxxer 2017-10-27 17:04:16

I don't think that is possible. But i don't know for shure. In C++ you allways need two pointer for a class method. Imagine a class like class a { void b(int){} };. Your Compiler will create the function intern like void __a__b(a * this, int){}. So you need a function pointer and also a class/struct pointer to actually call the member function. I've decided to use object as a copy so it would be save to actually return this class from a function. You could also use the object pointer but the function wrapper would be only valid in the same scope where the lambda was declared.

@Nikos 2018-09-26 06:03:00

@Noxxer Can this be usable as a method pointer as well?

@Noxxer 2018-09-27 17:27:28

For a object method you would need a pointer or a reference. This ja not possible with a implementation like this. The copy of a lambda object is in most cases ok. The copy of a object for a object method would mean you will Call the method on the wrong instance. I guess thats not what you want. The implementation needs as said a pointer or reference of the instance. : )

@Noxxer 2018-09-27 17:33:30

Also the implementation above expects the function operator () function. Which is a predefined function in lmabdas. I guess you want to use any function. So you have to store the method pointer also. The "automatic deduction" of function parameter becomes useless because you need to specifcy this as class template anyway to store the pointer correctly. : )

@n.m. 2018-11-10 14:36:54

This is not "passing capturing lambda as function pointer". This is "passing capturing lambda as an object that contains a function pointer among other things". There is a world of difference.

@janCoffee 2019-05-15 09:03:05

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

@Sneftel 2019-05-15 09:07:48

That lambda doesn't have a capture. The OP's issue is the capture, not having to deduce the function pointer type (which is what the + trick gets you).

@Passer By 2017-07-28 05:51:44

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

@fiorentinoing 2019-07-23 10:43:31

forcing the N integer to be declared would be an elegant way to remember the client to avoid overwriting the function pointers at compile time.

@smallscript 2018-07-04 18:37:16

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]).

@5gon12eder 2015-02-26 16:02:27

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.

  1. 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; } };
    }
    
  2. 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; }
      };
    }
    

@T.C. 2015-02-27 01:52:28

I'm quite amazed that that conditional expression actually works...

@Shafik Yaghmour 2015-02-27 01:56:48

@T.C. See this question for details why it works

@T.C. 2015-02-27 01:59:30

@ShafikYaghmour Yes, I know. I had to check [over.built]/p25 to verify that there's a built-in candidate for function pointers.

@Shafik Yaghmour 2015-02-27 12:44:38

@T.C. I was fascinated the first time I saw that work myself and so I added the comment for those who may not want to go through the trouble of figuring out why it works but are curious and it is good to know at least up to Visual Studio 2013 this does not work due to a bug. I had no doubts you could figure it out yourself ;-)

@5gon12eder 2015-02-27 14:58:33

@ShafikYaghmour Nice answer you've linked to, +1. I'll add a link to my answer.

@dan-man 2015-11-11 00:31:46

Note that in general, if you know the capture data at compile time, you can convert it to type data and then you're back to having a lambda with no capture - see this answer that I just wrote to another question (thanks to @5gon12eder's answer here).

@ar2015 2018-08-31 12:21:05

Shouldn't the object have a longer lifespan than the pointer function then? I would like to use it for glutReshapeFunc.

@TheNegative 2019-07-07 19:19:19

i don't recommend this suggestion, things that tend to work magically, introduce new errors. and practices that go along with those errors. if you want to use std::function, you should see all kinds of ways that std::function can be used. because some ways maybe something that you don't want.

@Hi-Angel 2019-08-15 15:04:33

This doesn't answer the question. If one could use std::function or a lambda — why wouldn't they? At the very least it's a more readable syntax. Usually one needs to use a function pointer to interact with C libraries (actually, with any external library), and sure you can't go modify it to accept an std::function or lambda.

@Shafik Yaghmour 2015-02-26 15:49:39

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.

@Nic Hartley 2018-11-17 00:00:45

Side note: One common solution used by C stuff is to pass a void* as the sole parameter. It's normally called a "user pointer". It's relatively lightweight, too, but does tend to require that you malloc out some space.

@beniekg 2015-12-19 17:38:14

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

Related Questions

Sponsored Content

37 Answered Questions

21 Answered Questions

[SOLVED] Why should I use a pointer rather than the object itself?

  • 2014-03-03 11:54:16
  • gEdringer
  • 294528 View
  • 1521 Score
  • 21 Answer
  • Tags:   c++ pointers c++11

13 Answered Questions

[SOLVED] What is a smart pointer and when should I use one?

22 Answered Questions

[SOLVED] What is a lambda (function)?

11 Answered Questions

[SOLVED] How do function pointers in C work?

  • 2009-05-08 15:49:17
  • Yuval Adam
  • 767468 View
  • 1159 Score
  • 11 Answer
  • Tags:   c function-pointers

9 Answered Questions

[SOLVED] What is a lambda expression in C++11?

3 Answered Questions

[SOLVED] Why is 'this' a pointer and not a reference?

6 Answered Questions

[SOLVED] Inheriting constructors

26 Answered Questions

[SOLVED] Why are Python lambdas useful?

1 Answered Questions

[SOLVED] Template Type Deduction with Lambdas

Sponsored Content