2

I have the following function:

template <typename Range>
Range FindFirstIf(Range rng, bool (*Function)(typename Range::ConstReference value))

To this function, I am trying to pass a lambda function like this:

rng = FindFirstIf(rng, [](const float& val) { return (v < 0.0f); });

Where rng is Range of List of floats, so Range::ConstReference is defined as const float&

My compiler (gcc) complains about type mismatch

C:\Programming\Collections\main.cpp|24|note:   mismatched types 'bool (*)(typename Range::ConstReference)' and 'main(int, char**)::< lambda(const float&) >'|

Can anybody tell me what is wrong with my code?

Edit:

When I pass function like this, it works:

bool (*func)(const float& v) = [](const float& v) { return v < 0.0f; };

When I try to use auto keyword, it is same problem as before:

auto func = [](const float& v) { return v < 0.0f; };
Alexander Bily
  • 925
  • 5
  • 18
  • 1
    You should be checking `val`, not `v`. –  Sep 06 '14 at 18:20
  • You already have an answer explaining what's wrong, but what might also be useful is a workaround: `rng = FindFirstIf(rng, +[](const float& v) { return (v < 0.0f); });`. The `+` forces the lambda to be converted to a function pointer directly (since the lambda class does not provide an overloaded `+` operator, but does provide a conversion-to-pointer operator to the result of which `+` can be applied), and GCC 4.8 doesn't detect that as a mismatched type. –  Sep 07 '14 at 02:32
  • @hwd thanks thats really nice workaround – Alexander Bily Sep 08 '14 at 11:22
  • @manlio I'm not sure why you felt it necessary to edit the tags here at all, but if you're going to do that, please make sure to use the right tags. The OP isn't using GCC 4.9. We can know that from the fact that the code isn't working for the OP. –  Sep 11 '14 at 10:09
  • @hvd From the accepted answer it seems to be a gcc bug resolved in v4.9 – manlio Sep 11 '14 at 10:10
  • @manlio Right. So the OP isn't using 4.9. If it should be tagged with a specific version of GCC (I'm neither saying that it should be nor that it shouldn't be), it should be tagged with the version the OP is using, the version that prompted the question. –  Sep 11 '14 at 10:12

1 Answers1

2

I suspect that either you have a type-o in your code, or you are using a version of gcc that does not completely implement lambdas (or possibly both).

If your example was:

[](const float& val) { return (val < 0.0f); }

(v -> val)

and if Range::ConstReference is a const float&, then the code is legal C++11.

The tricky part here is that some lambdas will implicitly convert to a function pointer. That is, those lambdas with no lambda-capture will convert to a function pointer with an identical signature.

This:

template <class Range>
Range
FindFirstIf(Range, bool (*Function)(typename Range::ConstReference value));

struct range
{
    using ConstReference = const float&;
};

int
main()
{
    range rng;
    rng = FindFirstIf(rng, [](const float& val) { return (val < 0.0f); });
}

compiles for me.

With a little poking around with online gcc compilers, this appears to be a bug in gcc 4.8, fixed in 4.9.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577