7

I have a function getTotal:

int getTotal( const HitMap& hitMap, bool( *accept)(int chan) )

where the second argument is a bool function specifying which members of the container hitMap should be added to the total.

I'm trying to call it with a lambda. This works:

auto boxresult =
getTotal(piHits, [](int pmt)->bool
{ return (pmt/100) == 1;} );

but this doesn't:

int sector = 100;
auto boxresult =
getTotal(piHits, [sector](int pmt)->bool
{ return (pmt/sector) == 1;} );

I get the error

cannot convert ‘main(int, char**)::<lambda(int)>’ to ‘bool (*)(int)’
for argument ‘2’ to ‘int getTotal(const HitMap&, bool (*)(int))’

from my compiler (GCC 4.6.3). I tried [&sector] and [=sector] but it didn't make any difference.

What am I doing wrong?

paco_uk
  • 445
  • 1
  • 5
  • 15

2 Answers2

16

When a lambda has a capture clause it can no longer be treated as a function pointer. To correct, use std::function<bool(int)> as the argument type for getTotal():

int getTotal( const HitMap& hitMap, std::function<bool(int)> accept)
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • 1
    Thanks `template int getTotal( const HitMap& hitMap,F accept )` works. Do you have a link where I can read about why it's different with function pointers? – paco_uk Apr 22 '13 at 11:36
  • Oh, [this](http://stackoverflow.com/a/7852154/1527126) makes sense. – paco_uk Apr 22 '13 at 11:43
  • 5
    @paco_uk: The reason is that when your lambda doesn't capture any data, to call it, the computer only needs to know where the code is stored. This means that a function pointer can be used to point to the code. When your lambda does capture data, it needs to know where the code is stored, and also to know what the data values are. This can't all be stored in a function pointer, so a functor is created behind the scenes, and that functor has a different type, because it stores different data. – Ken Bloom Apr 22 '13 at 11:44
  • @KenBloom thanks - that's even clearer! – paco_uk Apr 22 '13 at 11:45
  • There is a proposal for the next standard that would allow to bind stateful functions to function pointers. You can take a look [here](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3574.html). – Germán Diago Apr 22 '13 at 16:50
  • @GermánDiago: that proposal requires write access to executable memory, which is not going to work on many systems – newacct Apr 22 '13 at 18:27
3

The lambda function with capturing is not what you expect, you can use these ways:

template <typename F>
int getTotal( const HitMap& hitMap, F accept )
{

}

or

int getTotal( const HitMap& hitMap, std::function<bool(int)> accept )
{

}

The template based getTotal has better performance. Read more.

Community
  • 1
  • 1
masoud
  • 55,379
  • 16
  • 141
  • 208