5

From Lambda function passed as parameter I can compile the example:

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

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

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

Of course it can't link as FindFirstIf is not implemented.

However, when I did a similar thing:

template <class Range, class ValueType>
Range MyTest(Range, ValueType, bool(*Function)(ValueType value));

std::vector <int> vi;
double d = 0;
vi =       MyTest(vi, d, [](double val) { return (val < 0.0f); });

It has compilation error:

error C2784: 'Range MyTest(Range,ValueType,bool (__cdecl *)(ValueType))' : could not deduce template argument for 'bool (__cdecl *)(ValueType)' from 'main::'

why so? I thought by passing d in, ValueType can be deduced as double?

Community
  • 1
  • 1
athos
  • 5,550
  • 3
  • 40
  • 81
  • Not sure if it's because the type of `[](double val) { return (val < 0.0f); }` does not equal to `bool(*Function)(ValueType value)`. I've got a similar question before, maybe you can check it out. Here http://stackoverflow.com/questions/24606517/why-cant-i-deduce-template-argument-for-this-function – Marson Mao Oct 18 '16 at 06:25
  • If they are the same problem, the key point is that to deduce `ValueType`, it requires `ValueType` and `bool(*Function)(ValueType value)` to be both matched, but the type of lambda may be not match `bool(*Function)(ValueType value)` (i.e. they are convertible, but not equal) – Marson Mao Oct 18 '16 at 06:27
  • `vi = MyTest, double>(vi, d, [](double val) { return (val < 0.0f); });` will work!! – Praveen Oct 18 '16 at 06:47
  • 1
    @Praveen It works because deduction doesn't take place, but you have to explicitly specify the type and I suspect it is not what the OP wants. – skypjack Oct 18 '16 at 06:54

1 Answers1

2

Use this instead (note the +):

vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); });

Lambda functions can decay to function pointers in some cases, but they are not function pointers for themselves.
In other terms, deduction fails because it expects to work on a function pointer, but the lambda is not a function pointer, it could be converted of course, but first of all deduction must take place, but it cannot for the lambda is not the expected type, it could decay to it ... And so on.
By adding the + in front of the lambda, you force the conversion before it is passed to the function, thus MyTest receives an actual function pointer as expected and deduction goes on.

Here is a minimal, working example based on your code:

#include<vector>

template <class Range, class ValueType>
Range MyTest(Range, ValueType, bool(*Function)(ValueType value)) {}

int main() {
    std::vector <int> vi;
    double d = 0;
    vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); });
}
skypjack
  • 45,296
  • 16
  • 80
  • 161