1

So I've got a function like this:

template <typename T>
bool and_map(vector<T> v, function<bool(T)> fn) { ... }

And I want to pass it a vector and a lambda function like this:

[](int cell){ return(cell != -1); }

But I get an error which says there is no instance of and_map which takes these parameters.

When I do this it works:

template <typename T>
bool and_map(vector<T> v, function<bool(int)> fn) { ... }

How can I get it to work without specifying the parameter type of the passed function?

chmod 777 j
  • 547
  • 1
  • 5
  • 15
  • Lambdas are not `std::function`s. – T.C. Nov 13 '14 at 22:19
  • 2
    make the second parameter a non-deducible context for `T` like `bool and_map(std::vector v, typename identity>::type fn) { }` – Piotr Skotnicki Nov 13 '14 at 22:23
  • @Piotrs. I was just writing up a comment proposing the same solution when yours appeared. I think this is it. I'll leave it to you to post an answer. – Oguk Nov 13 '14 at 22:24
  • Oh, you're right, I forgot that while I was writing the comment ;-). And you are right, this (simple and common) solution is not mentioned there, which is unfortunate. – Oguk Nov 13 '14 at 22:30
  • 1
    just as a side note, `std::vector` is actually `std::vector`, don't forget about allocator's type when declaring a template – Piotr Skotnicki Nov 13 '14 at 22:37

2 Answers2

4

Here is the correct way to accept a functor:

template <typename T, typename F>
bool and_map(vector<T> v, F fn) { ... }
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

Having a function declared as:

template <typename T>
bool and_map(std::vector<T> v, std::function<bool(T)> fn)

a compiler tries to deduce a template type parameter T based on both arguments. However, a lambda expression is not std::function<T>, hence the compiler raises an error. To workaround that one can make the context of a second parameter (with std::function<bool(T)>) non-deducible with an identity trick:

template <typename T> struct identity { using type = T; };

template <typename T>
bool and_map(std::vector<T> v, typename identity<std::function<bool(T)>>::type fn)
{
    return {};
}

std::vector<int> v;
and_map(v, [](int cell){ return(cell != -1); });

so that type T will be deduced only based on the first argument, and then used to define the type of the second parameter.

DEMO

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160